当有多个子进程的SIGCHLD信号到达父进程的时候,如果父进程用wait等待,那么父进程在处理第一个达到的SIGCHLD信号的时候,其他的SIGCHLD信号被堵塞,而且信号不被缓存,这样就会导致信号丢失,这样会产生很多的僵尸进程。。解决办法是父进程用waitpid来等待子进程信号。。。

正好看到有人问这样一个问题

看unix网络编程第一卷的时候,碰到书上这样一个例子:
一个并发服务器, 每一个客户端连接服务器就fork一个子进程.书上讲到当同时有n多个客户端断开连接时,
服务器端同时有n多个子进程终止, 这时候内核同时向父进程发送n多个sigchld信号.
它的sigchld信号处理函数如下:
void sig_chld(int signo)
{
pid_t pid;
int stat; while((pid = waitpid(-, &stat, WNOHANG)) > ){
printf("child %d terminated\n", pid);
}
return;
} 我的问题是:既然sigchld是不可靠的信号,进程就不可能对sigchld进行排队, 直接丢弃了sigchld信号(当进程注册信号的时候,发现已有sigchld注册进未决信号, 因为内核同时发送多个sigchld).请问大家上面的代码是如何保证不产生僵尸进程的.谢谢! 超清晰的解答,来自与chinaunix论坛的flw大版主。。。: 根本就不需要找回来!
好比有五个进程,
不妨分别称为 p1 p2 p3 p4 p5,
一开始 p1 结束了,发了一个 SIGCHLD(s1),
这时父进程可能空闲了,于是开始处理这个信号,假设处理的过程中 p2 又结束了,又发了一个 SIGCHLD(s2),
这时候已经有两个信号了(一个正在处理,一个待处理),这时如果 p3 又结束了,那么它发的那个 SIGCHLD(s3) 势必会丢失,
丢失了怎么办?
没关系,因为那个信号处理函数是个循环嘛,
所以 while(waitpid()) 的时候,会把 p1 p2 p3 都处理的。
即使是很不幸,因为十分凑巧的原因,p3 没有被回收,导致变成僵尸进程了,也没关系,
因为还有 p4 p5 嘛,等到 p4 或者 p5 结束的时候,
又会再一次调用 while(waitpid()),到时候虽说这个 while(waitpid()) 是由 p4/p5 引起的,但是它也会一并把 p3 也处理的,因为它是个循环嘛! 如果还搞不懂,你就再看看 waitpid 的 man。 记住一点:
waitpid 和 SIGCHLD 没关系,即使是某个子进程对应的 SIGCHLD 丢失了,只要父进程在任何一个时刻调用了 waitpid,那么这个进程还是可以被回收的。 哎呀呀,简直费劲死了,其实说白了,就是一个“生产者-消费者”问题。
子进程结束的时候,系统“生产”出一个僵尸进程,
同时用 SIGCHLD 通知父进程来“消费”这个僵尸进程,
即使是 SIGCHLD 丢失了,没有来得及消费,
但是只要有一次消费,就会把所有的僵尸进程都处理光光!
(我再说一遍:因为,while(waitpid()) 是个循环嘛!)
我试了一下,wait好像也可以哦 #include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h> int main()
{
pid_t pc, pr;
pc = fork();
if(pc<){
printf("fork error\n");
}else if(pc == ){
printf("child pid = %d\n", getpid());
}else{
pr = fork();
if(pr == )
printf("child pid = %d\n", getpid());
else{ printf("parent pid = %d\n", getpid());
sleep();
while((pr = wait(NULL)) != -)
;
printf("this is parent process.\n");
sleep();
}
} exit();
}
运行后,
程序先输出
child pid =
parent pid =
child pid =
然后进入sleep(); 这时候 开另一个terminal, 运行 ps auxw | grep , 得到
0.0 0.0 pts/ S+ : : ./wait
0.0 0.0 pts/ Z+ : : [wait] <defunct>
0.0 0.0 pts/ Z+ : : [wait] <defunct>
0.0 0.0 pts/ S+ : : grep --color=auto 可以看到,两个子进程已经编程僵尸进程 然后20秒后,父进程执行了wait() ,输出
child pid =
parent pid =
child pid =
this is parent process. 这时候,到另一个终端里,再次运行ps
0.0 0.0 pts/ S+ : : ./wait
0.0 0.0 pts/ S+ : : grep --color=auto 可以看到两个僵尸子进程已经被回收。。 http://blog.chinaunix.net/uid-1911213-id-3387225.html

wait和waitpid的更多相关文章

  1. Linux 等待进程结束 wait() 和 waitpid()

    若子进程先于父进程结束时,父进程调用wait()函数和不调用wait()函数会产生两种不同的结果: --> 如果父进程没有调用wait()和waitpid()函数,子进程就会进入僵死状态. -- ...

  2. linux下使用fork,exec,waitpid模拟system函数

    代码如下: #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include &l ...

  3. 详解wait和waitpid函数

    #include <sys/types.h> /* 提供类型pid_t的定义 */ #include <sys/wait.h> pid_t wait(int *status) ...

  4. 父进程等待子进程结束 waitpid wait

    我们一直在强调一个概念就是进程是一个程序执行的实例,是内核在虚拟概念下创建的实体,它实例化的体现在用户态就是程序代码和代码使用的变量(存储空间),在内核态就是内核为我们每个进程所保存的数据结构(状态信 ...

  5. 系统调用wait、waitpid和exec函数

    本文介绍了Linux下的进程的一些概念,并着重讲解了与Linux进程管理相关的重要系统调用wait,waitpid和exec函数族,辅助一些例程说明了它们的特点和使用方法. 1.7 背景 在前面的文章 ...

  6. linux c学习笔记----进程创建(fork,wait,waitpid)

    1.pid_t fork(); (1)当一个进程调用了fork 以后,系统会创建一个子进程.这个子进程和父进程不同的地方只有他的进程ID 和父进程ID,其他的都是一样.就象符进程克隆(clone)自己 ...

  7. 对while((pid = waitpid(-1, &stat, WNOHANG)) > 0)不懂的地方,现在懂了

    while((pid = waitpid(-1, &stat, WNOHANG)) > 0) 需要写到信号处理函数中,假如有10个子进程 只要父进程能够收到最后一个信号,就能把前面丢失的 ...

  8. wait、waitpid 僵尸进程 孤儿进程

    man wait: NAME wait, waitpid, waitid - wait for process to change state SYNOPSIS #include <sys/ty ...

  9. 进程控制之wait和waitpid函数

    当一个进程正常或异常终止时,内核就向其父进程发送SIGCHLD信号.因为子进程终止是个异步事件(这可以在父进程运行的任何时候发生),所以这种信号也是内核向父进程发的异步通知.父进程可以选择忽略该信号, ...

  10. 【转】linux : waitpid函数

    原文网址:http://blog.csdn.net/jifengszf/article/details/3067841 [waitpid系统调用]       功能描述: 等待进程改变其状态.所有下面 ...

随机推荐

  1. 安装 ibm-java-x86_64-sdk-6.0-9.3.x86_64.rpm 的三步骤

    yum install libstdc++-devel.x86_64 yum install compat-libstdc++-33.x86_64 rpm -ivh ibm-java-x86_64-s ...

  2. 算法笔记_128:完美洗牌算法(Java)

    目录 1 问题描述 2 解决方案 2.1位置置换算法 2.2 走环算法   1 问题描述 有一个长度为2n的数组{a1,a2,a3,...,an,b1,b2,b3,...,bn},希望排序后变成{a1 ...

  3. [Swift A] - A Swift Tour

    首先说下自己对Swift语言的一点点看法,对于一个写过javascript和常年写java代码的人来说,学习Swift是一件很简单的事情.就像某某人说过,每个人都有弱点和优点,我到目前为止,只是初步的 ...

  4. Java之字节码(2) - .class文件格式详解

    转载来自 小介:去 年在读<深入解析JVM>的时候写的,记得当时还想着用自己的代码解析字节码的,最后只完成了一部分.现在都不知道还有没有保留着,貌似Apache有现 成的BCEL工程可以做 ...

  5. 转:函数指针数组的妙用(I)

    转自:http://blog.sina.com.cn/s/blog_4c78b35f010008hi.html 笔者在开发某软件过程中遇到这样一个问题,前级模块传给我二进制数据,输入参数为 char* ...

  6. Ubuntu下添加新分区并设置挂载点

    Ubuntu下添加新分区并设置挂载点   最近在做Android项目,可是解压根文件系统以后,就报警说硬盘不够.当初设置使用的大小为15G.不过扩展分区还是很方便的.当然首先你得设置添加使用的硬盘大小 ...

  7. HTML5 学习笔记 表单属性

    HTML5新的表单属性 HTML5 的form和input 标签添加了几个新的属性 <form>新属性 autocomplete novalidate input 新属性 autocomp ...

  8. pycharm 控制台字体背景颜色设定让你美到爆

    还在为你控制台字体颜色不入眼而发愁吗? 在某些特殊时刻想要改变下字体的颜色却无从下手而发愁吗? 那你就进来看一看,瞧一瞧,之需看2分钟,花2分钟理解,花3分钟练练手就能让你的控制能字体炫酷起来! 一. ...

  9. SIFT 、Hog 、LBP 了解

    SIFT.HOG.LBP,这三者都属于局部特征. 一.三者原理上的区别 1.SIFT:Scale-Invariant Feature Taransform,尺度不变特征变换. 尺度空间的极值检测:搜索 ...

  10. 删除mysql数据库表里的记录

    如果记录不再需要,可以用delete 命令进行删除,语法如下: DELETE FROM tablename [WHERE CONDITION] 例如,在emp 中将ename 为‘dony’的记录全部 ...