转自  http://blog.csdn.net/todd911/article/details/15028511

1.wait函数和waitpid函数

当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号。因为子进程终止是个异步事件,所以这种信号也是内核向父进程发的异步通知。父进程可以选择忽略信号,或者提供一个该信号的处理函数,对于这种信号默认动作是忽略它。调用wait或waitpid的进程可能会发生什么情况:

  • 如果其所有子进程都在运行,则阻塞。
  • 如果一个子进程已经终止,正等待父进程获取其终止状态,则取得该子进程的终止状态后返回。
  • 如果它没有任何子进程,则立即出错返回。
#include <sys/wait.h>
pid_t wait(int *statloc); //如果成功返回进程ID,0,如果出错返回-1.
pid_t waitpid(pid_t pid, int *statloc, int options); //如果成功返回进程ID,0(使用WNOHANG选项),如果出错返回-1.

这两个函数的区别是:

  • 在一个子进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可使调用者不阻塞。
  • waitpid并不等待在其调用之后的第一个终止子程序,它有若干个选项,可以控制它所等待的进程。
statloc是一个整型指针,如果statloc不是一个空指针,则终止进程的终止状态就存放在它所指向的单元内,如果不关心终止状态,则可将该参数指定为空指针。可以使用一下四个宏来查看进程的终止状态。
 
实践:
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h> void pr_exit(int status){
printf("status = %d\n", status);
if(WIFEXITED(status)){
printf("normal terminaton, exit status = %d\n", WEXITSTATUS(status));
}else if(WIFSIGNALED(status)){
printf("abnormal termination, signal number = %d%s\n",WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status)?"(core file generated)" : "");
#else
"");
#endif
}else if(WIFSTOPPED(status)){
printf("child stopped, signal number = %d\n", WSTOPSIG(status));
}
} int main(void){
pid_t pid;
int status; if((pid = fork()) < ){
perror("fork");
return -;
}else if(pid == ){
exit();
}
if(wait(&status) != pid){
perror("wait");
return -;
}
pr_exit(status); if((pid = fork()) < ){
perror("fork");
return -;
}else if(pid == ){
abort();
}
if(wait(&status) != pid){
perror("wait");
return -;
}
pr_exit(status); if((pid = fork()) < ){
perror("fork");
return -;
}else if(pid == ){
status /= ;
}
if(wait(&status) != pid){
perror("wait");
return -;
}
pr_exit(status); return ;
}
运行结果:
[yan@yanPC apue]$ ./a.out
status = 1792
normal terminaton, exit status = 7
status = 134
abnormal termination, signal number = 6(core file generated)
status = 136
abnormal termination, signal number = 8(core file generated)
 
waitpid可以等待一个特定的进程结束。对于waitpid函数中的pid参数的作用解释如下:
pid == -1    等待任意子进程,与wait等效。
pid > 0  等待进程ID等于pid的子进程。
pid == 0  等待其组ID等于调用进程组ID的任意子进程。
pid < -1 等待其组ID等于pid绝对值的任一子进程。
options参数使我们能进一步控制waitpid的操作。参数可以是0(不是用options),或是下表常量或运算的结果:
实践:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h> int main(void){
pid_t pid;
int status; if((pid = fork()) < ){
perror("fork");
return -;
}else if(pid == ){
sleep();
_exit();
} while(waitpid(pid,&status,WNOHANG) == ){
printf("no terminated process.\n");
sleep();
}
printf("child terminated.\n");
return ;
}  
运行结果:
yan@yan-vm:~/apue$ ./a.out
no terminated process.
no terminated process.
no terminated process.
no terminated process.
no terminated process.
child terminated.
使用了WNOHANG,因为没有结束的子进程,waitpid直接返回。
 
2.waitid函数
Single Unix Specification的XSI扩展包括了另一个取得进程终止状态的函数--waitid,该函数类似于waitpid,但提供了更多的灵活性。
#include <sys/wait.h>
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
//若成功则返回0,出错则返回-1.
id参数的作用与idtype的值相关,详细如下表:
options参数是下表各标志的按位或:
infop参数指向siginfo结构的指针,该结构包含了有关引起进程状态改变的生成信号的详细信息。
实践:
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h> int main(void){
pid_t pid, pid2;
siginfo_t info; if((pid = fork()) < ){
perror("fork");
return -;
}else if(pid == ){
sleep();
_exit();
}
while((pid2 = waitid(P_PID,pid,&info,WNOHANG)) == -){
printf("no terminated process %d.\n",pid2);
sleep();
} return ;
}
运行结果:
no terminated process -1.
no terminated process -1.
no terminated process -1.
no terminated process -1.
no terminated process -1.
no terminated process -1.
no terminated process -1.
no terminated process -1.
.......
按照说明,waitid一直返回-1,也就是一直出错,再看下进程状态。
yan       5147  0.0  0.0   2008   280 pts/2    S    14:10   0:00 ./a.out
yan       5148  0.0  0.0      0     0 pts/2    Z    14:10   0:00 [a.out] <defunct>
子程序已经僵死了,但是父进程无法回收它,这边真的不明白是什么原因,望高人指点~~~~
 
3.wait3和wait4函数
大多数UNIX系统实现了另外的两个函数wait3和wait4.历史上,这2个函数是UNIX系统的BSD分支沿袭下来的。它们提供的功能比POSIX.1函数wait,waitpid和waitid所提供的功能要多一个,这与附加参数rusage有关,该参数要求内核返回由终止进程及其所有子进程使用的资源汇总。
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
pid_t wait3(int *statloc, int options, struct rusage *rusage);
pid_t wait4(pid_t pid, int *statloc, int option, struct rusage *rusage);
//两个函数返回值,若成功,则返回进程ID,若出错,则返回-1.
资源统计信息包括用户CPU时间总量,系统CPU时间总量,页面出错次数,接受到信号次数等,下表列出了各个wait函数所支持的参数。
 
4.一种避免僵死进程的方法
使用2次fork,即使不对子进程进行回收也不会出现僵死进程。
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h> int main(void){
pid_t pid;
if((pid = fork()) < ){
perror("fork");
return -;
}else if(pid == ){
if((pid = fork()) < ){
perror("fork");
return -;
}else if(pid > ){
exit();
}else{
sleep();
printf("second child,parent pid = %d\n",getppid());
exit();
}
} if(waitpid(pid,NULL,) != pid){ //回收第一次fork的子进程
perror("waitpid");
return -;
}
return ;
}
运行结果:
yan@yan-vm:~/apue$ ./a.out
yan@yan-vm:~/apue$ second child,parent pid = 1
parent id为1,即被init收养了。 

wait系列的更多相关文章

  1. Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求

    上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...

  2. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  3. Angular杂谈系列1-如何在Angular2中使用jQuery及其插件

    jQuery,让我们对dom的操作更加便捷.由于其易用性和可扩展性,jQuer也迅速风靡全球,各种插件也是目不暇接. 我相信很多人并不能直接远离jQuery去做前端,因为它太好用了,我们以前做的东西大 ...

  4. ABP入门系列(1)——学习Abp框架之实操演练

    作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...

  5. 03.SQLServer性能优化之---存储优化系列

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 概  述:http://www.cnblogs.com/dunitian/p/60413 ...

  6. Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数

    上一篇:Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数 之前介绍了简单的路由以及传参,这篇文章我们将要学习复杂一些的路由以及传递其他附加参数.一个好的路由系统可以使我们 ...

  7. Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数

    上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...

  8. Angular2入门系列教程4-服务

    上一篇文章 Angular2入门系列教程-多个组件,主从关系 在编程中,我们通常会将数据提供单独分离出来,以免在编写程序的过程中反复复制粘贴数据请求的代码 Angular2中提供了依赖注入的概念,使得 ...

  9. 【疯狂造轮子-iOS】JSON转Model系列之二

    [疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...

  10. 【疯狂造轮子-iOS】JSON转Model系列之一

    [疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ...

随机推荐

  1. SAS学习笔记14 利用SAS绘制地图(二)

    笔记9讲过利用SAS绘制地图,这次接着讲 用中国各地(不含港澳台)的平均湿度数据来绘制地图 在地图上标出地名 宏%maplabel有9个参数,依次为:地图文件名.包含区域名称的数据集文件.输出的注释数 ...

  2. 2019杭电多校一 A. Blank (dp)

    大意: 长为$n$的数组, 每个位置范围$[0,3]$, $m$个限制$(l,r,x)$表示$[l,r]$内有$x$种数, 求方案数. 维护每个数字最后一次出现位置, 暴力$DP$ 实现时有个技巧是把 ...

  3. SVM的概率输出(Platt scaling)

    SVM的概率输出(Platt scaling) 2015-10-22 10:38:19 闲渔Love吉他 阅读数 8121 文章标签: Platt Scaling Calibr 更多 分类专栏: 计算 ...

  4. (十一)shiro与ssm整合

    所有代码在:here pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="h ...

  5. 验证码识别的免费 OCR

    在做接口自动化以及爬虫的过程中,验证码一般是个很烦的存在,其实大厂们已经做好了一些 OCR 供使用,这里介绍一下百度 OCR 的使用方法. 注册并生成应用 1.注册一个百度智能云账号:http://a ...

  6. python爬视频实例

    例:抓取PhotoShop视频教程 网址http://www.mxiaobei.com/?id=424 import requests import re from bs4 import Beauti ...

  7. pyodbc报错pyodbc.InterfaceError

    connection = pyodbc.connect(r'Driver={SQL Server Native Client 11.0};Server=...;Database=...;Trusted ...

  8. JavaScript--Function对象(函数)的声明和作用域

    Funtion 封装了可重复使用的代码块对象,函数名是一个引用函数对象的变量 声明提前:在程序开始执行之前,将var 变量和function函数提前声明 但赋值并不会提前 它的三种创建方法: 创建1 ...

  9. 两个重叠的div做前后翻转

    当需要做一个翻转卡片式的div时候,需要两个div的大小等大例如: 画出两个等大的div后,将他们重叠 图中的两个div做了重叠,做重叠时候用的属性是 position: absolute; 并且需要 ...

  10. S2-052

    前言 S2-052的RCE漏洞和以前的有些不同,不再是ognl表达式注入了,而是xml反序列化漏洞导致的RCE(另外还有S2-055漏洞是fastjson的反序列化漏洞).我复现的时候遇到一个坑,导致 ...