请教关于wait和waitpid

DoDoMouse 2015-05-19 08:12:23
在看unix网络编程的时候,在第五章书中提到在服务端处理僵死的子进程可以通过信号处理函数,但是调用wait并不足以防范僵死进程,原因是unix信号不排队。然后书中又说waitpid可以解决这个问题,因为有WNOHANG选项。
我就很奇怪,难道处理waitpid时候,信号就会排队了吗?不是照样会有信号丢失的问题出现?
...全文
154 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
DoDoMouse 2015-05-23
  • 打赏
  • 举报
回复
感谢大家的回复!
pengzhixi 2015-05-21
  • 打赏
  • 举报
回复
引用 6 楼 u011761982 的回复:
[quote=引用 2 楼 pengzhixi 的回复:]
void sig_chld(int signo)
{
        pid_t         pid;
        int         stat;
        
        while((pid = waitpid(-1, &stat, WNOHANG))  > 0) {
                printf("child %d terminated\n", pid);
        }
        
        return;
}
从网上copy的一段代码. wnohang的选项意味着不会阻塞一直等到某个子进程结束。那当一个子进程结束的时候进入到这个信号处理函数进行处理的时候这个时候另外一个子进程也结束了。那么意味着要重入这个处理函数了。只要这个处理函数式可重入的。那么无论有多少个子进程结束了,都会发SIGCHLD信号,都会被waitpid所处理。
你的意思是SIGCHLD信号会排队?我觉得不是这样子的吧。比如以下这个代码,如果有n个信号同时产生,你觉得会打印几遍hello:

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

[/quote] 这有什么关系呢?因为你已经进入了这个循环执行waitpid了。waitpid可不需要SIGCHLD信号,只要有子进程挂了就会返回。只是说waitpid借助第一个SIGCHLD信号发挥作用。他本身处理是与SIGCHLD信号没关系。简单的说waitpid等待的不是SIGCHLD,而是子进程的死亡状态,仅此而已。
DoDoMouse 2015-05-20
  • 打赏
  • 举报
回复
引用 2 楼 pengzhixi 的回复:
void sig_chld(int signo)
{
        pid_t         pid;
        int         stat;
        
        while((pid = waitpid(-1, &stat, WNOHANG))  > 0) {
                printf("child %d terminated\n", pid);
        }
        
        return;
}
从网上copy的一段代码. wnohang的选项意味着不会阻塞一直等到某个子进程结束。那当一个子进程结束的时候进入到这个信号处理函数进行处理的时候这个时候另外一个子进程也结束了。那么意味着要重入这个处理函数了。只要这个处理函数式可重入的。那么无论有多少个子进程结束了,都会发SIGCHLD信号,都会被waitpid所处理。
你的意思是SIGCHLD信号会排队?我觉得不是这样子的吧。比如以下这个代码,如果有n个信号同时产生,你觉得会打印几遍hello:

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

DoDoMouse 2015-05-20
  • 打赏
  • 举报
回复
引用 4 楼 qq120848369 的回复:
信号不排队的意思是:可能有2个子进程都退出了,向父进程发来了总共2个SIGCHLD信号,由于信号不排队,所以会合并成1个事件,调用信号处理函数一次。 如果你在信号处理函数里只wait一次,那么就会漏掉1个子进程的资源没有回收。所以要在信号处理函数里循环调用不阻塞的waitpid函数,直到其返回值表明没有更多子进程可以回收了,这里有一个前提就是信号处理函数被调用期间,对应的信号会被线程阻塞,这样在信号处理函数期间到达的SIGCHLD信号就不会丢失,可以保障信号函数处理退出后马上被再次唤起。
是不是指在调用waitpid的时候,也有可能只有一个SIGCHLD信号,但是父进程调waitpid会查询还有没有子进程是僵死状态,如果有的话那就回收?
FightForProgrammer 2015-05-19
  • 打赏
  • 举报
回复
waitpid是非阻塞的。每当有子进程退出的信号都能接收到。而wait阻塞,如果不是最后一个进程退出,而是其他子进程退出,那么就接收不到退出信号,然后就成了僵尸进程了
pengzhixi 2015-05-19
  • 打赏
  • 举报
回复
void sig_chld(int signo)
{
        pid_t         pid;
        int         stat;
        
        while((pid = waitpid(-1, &stat, WNOHANG))  > 0) {
                printf("child %d terminated\n", pid);
        }
        
        return;
}
从网上copy的一段代码. wnohang的选项意味着不会阻塞一直等到某个子进程结束。那当一个子进程结束的时候进入到这个信号处理函数进行处理的时候这个时候另外一个子进程也结束了。那么意味着要重入这个处理函数了。只要这个处理函数式可重入的。那么无论有多少个子进程结束了,都会发SIGCHLD信号,都会被waitpid所处理。
假正经的班长 2015-05-19
  • 打赏
  • 举报
回复
程序被杀死之后,为了在垂死之际将最后的状态信息留给父进程,才留下了僵尸进程,等待父进程使用waitpid来“收尸”,wait内部也是调用了waitpid。至于子进程退出的信号,通常被忽略掉了。
qq120848369 2015-05-19
  • 打赏
  • 举报
回复
信号不排队的意思是:可能有2个子进程都退出了,向父进程发来了总共2个SIGCHLD信号,由于信号不排队,所以会合并成1个事件,调用信号处理函数一次。 如果你在信号处理函数里只wait一次,那么就会漏掉1个子进程的资源没有回收。所以要在信号处理函数里循环调用不阻塞的waitpid函数,直到其返回值表明没有更多子进程可以回收了,这里有一个前提就是信号处理函数被调用期间,对应的信号会被线程阻塞,这样在信号处理函数期间到达的SIGCHLD信号就不会丢失,可以保障信号函数处理退出后马上被再次唤起。

64,680

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧