进程控制 创建、等待、替换

本文深入解析Linux系统中进程创建、等待及程序替换的核心机制。详细介绍fork()、wait()、waitpid()函数的使用场景及返回值含义,以及exec函数族如何实现进程的代码和数据完全替换,涵盖进程间通信的基础知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程创建:
首先认识一下fork()函数:

pid_t fork();
函数作用:
创建一个子进程;
返回值:
1.调用成功,子进程返回0;父进程返回子进程的PID;
2.调用失败,返回-1;

子进程创建成功,子进程会采用写时拷贝的方式拷贝父进程的数据;

进程等待:
先认识两个函数:
pid_t wait(int* status);
pid_t waitpid(pid_t pid,int* status,int option);

先来说wait函数:
父进程调用wait函数可以回收子进程终止信息;该函数有以下功能:
1.阻塞等待子进程退出;
2.回收子进程资源;
3.获取子进程结束状态(退出原因);

wait函数调用成功 则返回等待的子进程的PID,失败:则返回-1(说明没有子进程),status,传出参数,用来获取子进程退出的状态,不关心子进程退出状态,则可以设置为NULL, 它占4个字节,低8位,退出信号; 次低8位,退出码;

用一些特定的宏和传出参数status搭配来判断进程终止状态:

  1. WIFEXITED(status) 为非0 → 进程正常结束
    WEXITSTATUS(status) 如上宏为真,使用此宏 → 获取进程退出状态 (exit的参数)
  2. WIFSIGNALED(status) 为非0 → 进程异常终止
    WTERMSIG(status) 如上宏为真,使用此宏 → 取得使进程终止的那个信号的编号。

接着说waitpid函数:
参数:
pid>0: 只等待子进程ID等于pid的子进程;
pid=-1:等待任何一个子进程,和wait一样;
pid==0等待其组ID等于调⽤用进程组ID的任一个子进程。
pid<-1等待其组ID等于pid绝对值的任一子进程。

status参数上面已经介绍过了;

option参数有以下两种:
1.如果使用了WNOHANG参数,即使没有子进程退出,它也会立即返回,返回一个0值,不会像wait那样永远等下去.

2.如果使用了WUNTRACED参数,则子进程进入暂停则马上返回,但结束状态不予以理会.

如果我们不想使用它们,也可以把options设为0,如:ret=waitpid(-1,NULL,0);
如果使用上面两个宏,waitpid就是非阻塞等待; 如果不使用,用0代替,则就会和wait一样 变为阻塞式等待;

程序替换:
先来说一下exec函数族:
fork创建子进程成功后,子进程执行的是和父进程相同的代码(也有可能执行不同的代码分支),子进程往往会调用exec函数,以执行不同的程序,当进程调用一种exec函数时,该进程用户空间代码和数据会完全被新程序代替(包括一些堆、栈数据),调用exec函数并不会创建新进程,原有的进程ID不会变;

exec族函数有以下6种:

#include<unistd.h>

int execl(const char* path,const char* argc, ...);    //库函数
// 参数:   路径、具体操作,以NULL结尾
int execlp(const cahr* file,const char* argc,...);    //库函数
//参数: 文件名,具体操作,以NULL结尾
int execle(const char* path,const char* argc,...,const char* envp[])  //库函数
//参数: 路径、具体操作,以NULL结尾、环境变量(NULL结尾)

int execv(const char* path,char* const argv[])   //库函数
//参数: 路径、指令数组(存放需要执行的指令)以NULL结尾
int execvp(const char* file,char* const argv[])  //库函数
//参数: 文件名、 同上
int execve(const char* path,char* const argv[],char* const envp[]) 
//系统调用
//参数: 路径、指令数组(以NULL结尾)、环境变量(以NULL结尾)

//exec函数族的具体用法:
#include<unistd.h>
int main()
{
char* const argv={"ls","-a",NULL};
char* const envp={"PATH=/bin:/usr/bin", "TERM=console", NULL};
execl("/bin/ps", "ps", "-ef", NULL); 
execlp("ps", "ps", "-ef", NULL);
execle("ps", "ps", "-ef", NULL, envp);
execv("/bin/ps", argv);
execvp("ps", argv);
execve("/bin/ps", argv, envp);
}

//总结一下:
//1.带l的   就是要把指令列举出来
//2.带v的  参数直接用数组(数组里面放的是指令)
//3.带p的  第一个参数路径可以不写全,只写一个文件名即可;
//4.带e的  多一个参数,envp[], 里边放的环境变量值,意思是构建一份
//新的环境变量表给它,构造的环境变量不会继承原有的;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值