文章目录

  • 1. wait()函数
  • 2. waitpid()函数
  • 3. wait() 和 waitpid() 用法和比较


1. wait()函数

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);

  进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。

参数

  • 参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就像这样:pid = wait(NULL);

返回值

  • 如果成功,wait会返回被收集的子进程的进程ID;
  • 如果调用进程没有子进程,调用就会失败,此时wait返回-1,同时errno被置为ECHILD。


2. waitpid()函数

#include <sys/wait.h>
#include <sys/types.h>
pid_t waitpid(pid_t pid, int *status, int options)

  从本质上讲,系统调用waitpid和wait的作用是完全相同的,但waitpid多出了两个可由用户控制的参数pid和options,从而为我们编程提供了另一种更灵活的方式。

参数

  • status:参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。但如果我们对这个子进程是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可以设定这个参数为NULL,就像这样:pid = waitpid(-1, NULL, 0);
  • pid:从参数的名字pid和类型pid_t中就可以看出,这里需要的是一个进程ID。但当pid取不同的值时,在这里有不同的意义。
    ① pid>0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去(阻塞在waitpid()函数这里);
    ② pid=-1时,等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样;   
    ③ pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬;
    ④ pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值;
  • options:提供了一些额外的选项来控制waitpid,目前在Linux中只支持:WNOHANGWUNTRACED两个选项,这是两个常数,可以用"|"运算符把它们连接起来使用;比如ret=waitpid(-1,NULL,WNOHANG | WUNTRACED); 如果我们不想使用它们,也可以把options设为0,如ret=waitpid(-1,NULL,0); 如果使用了WNOHANG参数调用waitpid,即使没有子进程退出,它也会立即返回,不会像wait那样永远等下去。而WUNTRACED参数,由于涉及到一些跟踪调试方面的知识,加之极少用到,可以自行查阅相关材料。
  • 返回值:waitpid的返回值比wait稍微复杂一些,一共有三种情况:
    ① 当正常返回的时候,waitpid返回收集到的子进程的进程ID;
    如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;      
    ③ 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;当pid所指示的子进程不存在,或此进程存在,但不是调用进程的子进程,waitpid就会出错返回,这时errno被设置为ECHILD


3. wait() 和 waitpid() 用法和比较

(一)wait()只能处理一个子进程的SIGCHLD,如果多个并发子进程同时关闭,则会出现僵尸进程,而用waitpid()则会避免这种情况

void sig_chld(int signo)
{ pid_t pid; int stat; while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0) //非阻塞printf("child %d terminated\n", pid); return;
}

这段代码体现在当有多个子进程结束并几乎同时提交信号时,waitpid可使所有被提交的信号得到处理,而不会留下zombie。解决办法:

  • ① 轮询wait返回的pid,直到等待到所有的子进程pid;
  • ② 使用waitpid侦听特定的pid;
  • while(waitpid(-1, NULL, WNOHANGUP) > 0));进行一直地非阻塞等待,直至父进程回收完所有地结束子进程

如果使用信号:子进程结束发出信号,主进程侦听wait处理所有信号-----所有5个信号结束信号SIGCHLD都在信号处理函数执行之前产生,而信号处理函数只执行一次,因为Unix信号一般是不排队的,如果是不同信号则进入不同的处理函数,但是同一信号只能进入一次处理函数,后面的则丢失了。


其它: 调用 wait&waitpid 来处理终止的子进程

pid_t wait(int * status);
pid_t waitpid(pid_t pid,int *status, int options);
  • 两个函数都返回两个值:函数的返回值和终止的子进程ID,而waitpid()子进程终止的状态则是通过status指针返回的;
  • wait()函数等待第一个终止的子进程,而waitpid()函数则可以指定等待特定的子进程;
  • 这的区别可能会在下面这种情况时表现得更加明显:
      当同时有5个客户连上服务器,也就是说有五个子进程分别对应了5个客户,此时,五个客户几乎在同时请求终止,这样一来,几乎同时,五个FIN发向服务器,同样的,五个SIGCHLD信号到达服务器,然而,UNIX的信号往往是不会排队的,显然这样一来,信号处理函数将只会执行一次,残留剩余四个子进程作为僵尸进程驻留在内核空间。此时,正确的解决办法是利用waitpid(-1, &stat, WNOHANG)防止留下僵尸进程。其中的pid为-1表明等待任一个子进程,而WNOHANG选择项通知内核在没有已终止进程项时不要阻塞。
  • wait()函数其实是waitpid()函数的特例,也即wait()函数是封装waitpid()得来的。
static inline pid_t wait(int * wait_stat) {return waitpid(-1, wait_stat, 0);  //返回值和错误
}

waitpid提供了wait函数不能实现的3个功能:

  • ① waitpid等待特定的子进程, 而wait则返回任一终止状态的子进程;
  • ② waitpid提供了一个wait的非阻塞版本;
  • ③ waitpid支持作业控制。用于检查 wait() 和 waitpid() 两个函数返回终止状态的宏: 这两个函数返回的子进程状态都保存在status指针中,用以下3个宏可以检查该状态:
    WIFEXITED(status): 若为正常终止, 则为真。此时可执行 WEXITSTATUS(status): 取子进程传送给exit或_exit参数的低8位.
    WIFSIGNALED(status): 若为异常终止, 则为真。此时可执行 WTERMSIG(status): 取使子进程终止的信号编号.
    WIFSTOPPED(status): 若为当前暂停子进程, 则为真。此时可执行 WSTOPSIG(status): 取使子进程暂停的信号编号

wait()函数和waitpid()函数详解相关推荐

  1. 在python中使用关键字define定义函数_python自定义函数def的应用详解

    这里是三岁,来和大家唠唠自定义函数,这一个神奇的东西,带大家白话玩转自定义函数 自定义函数,编程里面的精髓! def 自定义函数的必要函数:def 使用方法:def 函数名(参数1,参数2,参数-): ...

  2. 函数assert()详解

    函数assert()详解: 断言assert是一个宏,该宏在<assert>中,,当使用assert时候,给他个参数,即一个判读为真的表达式.预处理器产生测试该断言的代码,如果断言不为真, ...

  3. php。defined,PHP defined()函数的使用图文详解

    PHP defined()函数的使用图文详解 PHP defined() 函数 例子 定义和用法 defined() 函数检查某常量是否存在. 若常量存在,则返回 true,否则返回 false. 语 ...

  4. python中tile的用法_python3中numpy函数tile的用法详解

    tile函数位于python模块 numpy.lib.shape_base中,他的功能是重复某个数组.比如tile(A,n),功能是将数组A重复n次,构成一个新的数组,我们还是使用具体的例子来说明问题 ...

  5. Delphi Format函数功能及用法详解

    DELPHI中Format函数功能及用法详解 DELPHI中Format函数功能及用法详解function Format(const Format: string; const Args: array ...

  6. python中的json函数_python中装饰器、内置函数、json的详解

    装饰器 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象. 先看简单例子: def run(): time.sleep(1 ...

  7. 如何使用指向类的成员函数的指针(详解!)

    原文:如何使用指向类的成员函数的指针(详解!) 另外一篇英文参考:Member Function Pointers and the Fastest Possible C++ Delegates 我们首 ...

  8. php时间函数引入,PHP日期和时间函数的使用示例详解

    (1)查看日期函数拓展 phpinfo() phpinfo(); 打开上述页面之后,可以看到以下,证明已经安装日期拓展 浏览器输入php.net访问php的文档 (2)设置时区 方式一:修改配置文件p ...

  9. python def函数报错详解_python自定义函数def的应用详解

    这篇文章主要介绍了python自定义函数def的应用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 这里是三岁,来和大家唠唠 ...

最新文章

  1. kali linux解密栅栏密码,犯罪大师上帝之眼答案最新
  2. Know more about RAC statistics and wait event
  3. 那些年我们程序员欠下的技术债
  4. r语言和python的区别_机器学习怎样开始比较好?Python还是R语言?
  5. Protobuf从安装到配置整理帖
  6. php输出tab,设置Tab按钮列表 · DolphinPHP1.5.0完全开发手册-基于ThinkPHP5.1.41LTS的快速开发框架 · 看云...
  7. Leetcode题库 32.从上到下打印二叉树(层次遍历 C实现)
  8. 三方协议,档案,工龄,保险,户口,
  9. Xml xpath samples
  10. webbench接口并发测试
  11. 为什么不能在字符串上使用switch语句?
  12. JS的构造及其事件注意点总结
  13. java和python哪个运行速度快_为什么Python代码的运行速度比较慢呢?这会影响Python语言的扩张吗?...
  14. NATAPP内网穿透使用
  15. tomcat8的apr模式配置SLL证书
  16. python爬虫-京东商品详情爬取
  17. Flask--网页微信登陆示例
  18. 【Java】我的世界Java版外挂制作 [2] - 游戏内GUI
  19. 建设容器云平台之前不能忽视3个评估,你的企业能得多少分? | 某银行最佳实践分享
  20. iphone6s维修定位服务器,iphone6s修理点

热门文章

  1. 部署SQLServer2008R2导致K金蝶软件恢复数据报master.dbo.t_kdaccount_gl无效解决方案
  2. HTML5 Canvas动态绘制心型线和玫瑰线
  3. 刚刚发现在博客园的博客排行榜[前200人]中我的blog竟然排在第47位
  4. day02--java基础编程:变量,数据类型,类型转换,运算规则,Scanner,运算符,分支结构,循环(随机数),方法,重载,可变参数,递归,数组,冒泡排序
  5. (下)苹果有开源,但又怎样呢?
  6. DOS命令的返回值“errorlevel”和基础DOS命令小结
  7. Linux系统安装JDK8
  8. 领英关闭中国业务领英职场!怎么保住自己的领英账号和好友并继续使用领英搜索开发客户?
  9. 【2022/08/11】文件的上传(FileUpload)
  10. 【爬虫】QQ空间照片下载