Linux进程等待和替换

一、进程等待

1.进程等待的作用

在一个程序中,如果父进程创建子进程后,子进程先于父进程退出,父进程如果什么都不做,就会产生僵尸进程的问题,对于这种情况,父进程此时就需要等待子进程退出,回收子进程资源,接收子进程的退出返回值,避免产生僵尸进程。

2.如何实现进程等待

阻塞接口:为了完成一个功能发起一个调用,但调用完成条件不具备,则接口一直等待不返回

非阻塞接口:为了完成一个功能发起一个调用,但调用完成条件不具备,则立即报错返回

(1) wait()函数  (阻塞接口)

函数原型:     pid_t wait(int*status);

函数头文件:#include<sys/types.h>

                      #include<sys/wait.h>

返回值:成功则返回进程的pid,失败则返回-1

参数status:获取进程退出状态,不关心可以设置为NULL

注:wait()函数返回值并不是status,它返回的是进程pid,而status是进程退出的状态,被保存在其低16位中的高8位,status不能简单的当作整形来看待,可以当作位图来看待,具体如下:(只研究status低16位)

 core dump标志位默认为0

如果进程正常退出,则 低6位异常值为0,返回的数据就是低16位代表的十进制数

如果进程异常退出,则低6位不为0,返回的数据也是低16位代表的十进制数

在进程退出的时候,我们通常会用exit()函数,exit(a)函数中的参数a就为status的退出状态,但是此数不能过大,因为status 的退出状态只接受一个字节(8位),超出的数位就会被截断

具体实现:

运行结果:

(2) waitpid()函数

对于wait()函数来说,其只能进行阻塞等待,就是将父进程先阻塞,知道父进程接收到子进程的退出返回值,父进程才开始继续往下执行,资料利用率低。此时就有一种新的等待函数waitpid()函数

它既可以阻塞等待也可以非阻塞等待,同时,它既可以等待任意一个子进程退出,也可以等待指定的一个子进程退出

函数原型:pid_ t waitpid(pid_t Pid, int *status, int options);
返回值:
当正常返回的时候 waitpid 返回收集到的子进程的进程 ID
如果设置了选项 WNOHANG, 而调用中 waitpid 发现没有已退出的子进程可收集 , 则返回 0
如果调用中出错 , 则返回 -1, 这时 errno 会被设置成相应的值以指示错误所在;
参数:
Pid
Pid=-1,等待任一个子进程。与wait等效。
Pid>0.等待其进程ID与pid相等的子进程。
status:
WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
WEXITSTATUS(status): WIFEXITED 非零,提取子进程退出码。(查看进程的退出码)
options:
WNOHANG: 设置为WNOHANG,表示此时为非阻塞等待,若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该 子进程的ID。
具体实现:

运行结果:

 

 二、进程替换

1.替换原理:

替换一个进程正在调度管理的程序

fork 创建子进程后执行的是和父进程相同的程序 ( 但有可能执行不同的代码分支 ), 子进程往往要调用一种 exec 函数 以执行另一个程序。 当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。 
2.替换函数
int execve(const char *path, char *const argv[], char *const envp[]);
功能:将path 这个路径名所指定的程序加载到内存中,然后让当前程序调度管理这个程序的运行
           argv:用于设定这个程序的的运行参数
           envp:用于设定这个程序的环境变量
返回值:替换成功没有返回值,因为替换成功就运行其他程序了
               替换失败返回 -1 
注:execve()中,path需要自己指定,envp也需要自己指定  execve("./bin/ls",argv,env)
int execvp(const char *file, char *const argv[]);
与上述execve相类似,第一个参数path不需要指定路径,默认会在PATH环境变量指定的路径下去找
execvp("ls",argv)
int execv(const char *path, char *const argv[]);
第一个参数需要自己设定,但不需要设定环境变量                 execve("./bin/ls",argv)
argv[]={"ls","-a","-l","NULL}
int execl(const char *path, const char *arg, ...);
第一个参数需要自己设定路径,不需要自己设置环境变量,第二个参数argv为不定参数
execl("./bin/ls","ls","-l","-a",NULL);
int execlp(const char *file, const char *arg, ...);
第一个参数不需要自己设定路径,不需要自己设置环境变量,第二个参数argv为不定参数
execlp("ls","ls","-l","-a",NULL);
int execle(const char *path, const char *arg, ...,char *const envp[]);
第一个参数需要自己设定路径,需要自己设置环境变量,第二个参数argv为不定参数
execlp("./bin/ls","ls","-l","-a",NULL,env);
具体实现:
运行结果:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值