wait 和 waitpid 详解及代码示例
- 1. 父子进程处理历史及父进程处理方法
- 2. wait
-
- 2.1 wait 功能
- 2.2 wait 接口
- 2.3 wait 原理
-
- 2.3.1 wait 源码实现
- 2.4 wait 参数:
- 2.5 wait 返回值:
- 2.6 wait 代码示例
- 3. waitpid
-
- 3.1 waitpid 功能
- 3.2 waitpid 接口
- 3.3 waitpid 原理
- 3.4 waitpid 参数:
- 3.5 waitpid 返回值:
- 3.6 waitpid 代码示例
- 参考
1. 父子进程处理历史及父进程处理方法
进程用wait和waitpid函数清理僵尸进程,父进程可以阻塞等待子进程结束,也可以非阻塞地查询是否有子进程结束等待清理(也就是轮询的方式)。
采用第一种方式,父进程阻塞了就不能处理自己的工作了;
采用第二种方式,父进程在处理自己的工作的同时还要记得时不时地轮询一下,程序实现复杂。
其实,子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。
事实上,由于UNIX的历史原因,要想不产生僵尸进程还有另外一种办法:父进程调用sigaction将SIGCHLD的处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程。系统默认的忽略动作和用户用sigaction函数自定义的忽略通常是没有区别的,但这是一个特例。此方法对于Linux可用,但不保证在其它UNIX系统上都可用。请编写程序验证这样做不会产生僵尸进程。
2. wait
2.1 wait 功能
简单点就是:销毁子进程。
wait()就是得到子进程的返回码,等于就是为子进程“收尸”,否则子进程会变僵尸进程
2.2 wait 接口
pid_t wait(int *status)
2.3 wait 原理
进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
2.3.1 wait 源码实现
wait就是经过包装的waitpid
察看<内核源码目录>/include/unistd.h文件349-352行就会发现以下程序段:
static inline pid_t wait(int * wait_stat)
{
return waitpid(-1,wait_stat,0);
}
2.4 wait 参数:
参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就象下面这样:
pid = wait(NULL);
2.5 wait 返回值:
如果成功,wait会返回被收集的子进程的进程ID
如果调用进程没有子进程,调用就会失败,此时wait返回-2,同时errno被置为ECHILD。
2.6 wait 代码示例
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
int main(int argc, char* argv[]){
int childpid;
pid_t pid;
pid = fork();
if(pid > 0)
{
printf("parent execl done\n");
wait(NULL);
}else if(0 == pid)
{
execl("/bin/ls", "ls", "-l", NULL);
printf("pid execl done\n");
}else{
printf("error pid < 0 \n");
}
printf("exiting...\n");
return 0;
}
结果:
[root@glusterfs home]# gcc test.c
[root@glusterfs home]# ./a.out
parent execl done
total 24
-rwxr-xr-x 1 root root 8632 Dec 4 09:50 a.out
-rw-r--r-- 1 root root 439 Dec 4 09:50 test.c
exiting...
[root@glusterfs home]#
3. waitpid
3.1 waitpid 功能
-
从本质上讲,系统调用waitpid和wait的作用是完全相同的。
-
但waitpid多出了两个可由用户控制的参数pid和options,从而为我们编程提供了另一种更灵活的方式。
3.2 waitpid 接口
pid_t waitpid(pid_t pid,int *status,int options)
3.3 waitpid 原理
从本质上讲,系统调用waitpid和wait的作用是完全相同的
就是如下:
进程一旦调用了waitpid,就立即阻塞自己,由waitpid自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,waitpid就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,waitpid就会一直阻塞在这里,直到有一个出现为止。
3.4 waitpid 参数:
1. status 同上
2. pid: 从参数的名字pid和类型pid_t中就可以看出,这里需要的是一个进程ID。
但当pid取不同的值时,在这里有不同的意义。
2.1 pid>0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。
2.2 pid=-1时,等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样。
2.3 pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。
2.4 pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。
3. options: options提供了一些额外的选项来控制waitpid
目前在Linux中只支持 WNOHANG 和 WUNTRACED 两个选项,这是两个常数,可以用"|"运算符把它们连接起来使用
如果使用了WNOHANG参数调用waitpid,即使没有子进程退出,它也会立即返回,不会像wait那样永远等下去。
而WUNTRACED参数,由于涉及到一些跟踪调试方面的知识,加之极少用到
可以通过用常量WNOHANG和WUNTRACED的不同组合来设置options,修改默认行为:
1. WNOHANG :如果没有等待集合中的任何子进程终止,那么就立即返回(返回值为0)0
2. WUNTRACED :挂起调用进程的执行,直到等待集合中的一个进程变成终止的或者被暂停。
返回的PID为导致返回的终止或暂停了进程的PID。
3. WNOHANG | WUNTRACED:立即返回,如果没有等待集合中的任何子进程停止或终上,
那么返回值为0,或者返回值等于那个被停止或者终止子进程的PID
示例:
ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);
如果我们不想使用它们,也可以把options设为0,如:
ret=waitpid(-1,NULL,0);
3.5 waitpid 返回值:
waitpid的返回值比wait稍微复杂一些,一共有3种情况:
1. 当正常返回的时候,waitpid返回收集到的子进程的进程ID;
2. 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
3. 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
如果调用进程没有子进程,那么waitpid返回-1,并且设置errno为ECHILD。
如果waitpid函数被一个信号中断,那么它返回-1,并设置为EINTR。
3.6 waitpid 代码示例
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
int main(int argc, char* argv[]){
int childpid;
pid_t pid;
pid = fork();
if(pid > 0)
{
printf("parent execl done\n");
waitpid(-1,0,0);
}else if(0 == pid)
{
execl("/bin/ls", "ls", "-l", NULL);
printf("pid execl done\n");
}else{
printf("error pid < 0 \n");
}
printf("exiting...\n");
return 0;
}
结果:
[root@glusterfs home]# gcc waitpid.c
[root@glusterfs home]# ./a.out
parent execl done
total 28
-rwxr-xr-x 1 root root 8640 Dec 7 14:29 a.out
-rw-r--r-- 1 root root 374 Dec 7 14:29 waitpid.c
exiting...
[root@glusterfs home]#
参考
https://www.cnblogs.com/LUO77/p/5804436.html
今天的文章wait后面的代码执行吗_javascript代码分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/58378.html