免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 43452 | 回复: 71
打印 上一主题 下一主题

关于SIGCHLD的不排队,丢弃的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-09-15 14:49 |只看该作者 |倒序浏览
看unix网络编程第一卷的时候,碰到书上这样一个例子:
一个并发服务器, 每一个客户端连接服务器就fork一个子进程.书上讲到当同时有n多个客户端断开连接时,
服务器端同时有n多个子进程终止, 这时候内核同时向父进程发送n多个sigchld信号.它的sigchld信号处理
函数如下:
void sig_chld(int signo)
{
       pid_t   pid;
       int     stat;
      
       while((pid = waitpid(-1, &stat, WNOHANG)) > 0){
               printf("child %d terminated\n", pid);
       }
        return;
}

我的问题是:既然sigchld是不可靠的信号,进程就不可能对sigchld进行排队, 直接丢弃了sigchld信号(当进程注册信号的时候,发现已有sigchld注册进未决信号, 因为内核同时发送多个sigchld).请问大家上面的代码是如何保证不产生僵尸进程的.谢谢!

论坛徽章:
0
2 [报告]
发表于 2006-09-15 15:28 |只看该作者
高人指点啊

论坛徽章:
0
3 [报告]
发表于 2006-09-15 16:03 |只看该作者
用消息队列吧,子进程退出前把自已的PID写进队列
然后父进程去读,不过pid = waitpid(-1, &stat, 0);
让父进程阻塞在调用这块,不过如果你想让waitpid快带返回也行, 如果没接到子进程退出信号,你可以把这个PID再写进去,然后继续读,直到接到SIGCHLD为止。

以前在项目中遇到过此问题,大量的并发进程往往造成很多的僵死进程,以至于程序无法响应,当时被这个问题弄得很头痛,直到想到这个方法以后才有效的解决了上述问题。

为方法就等于实现了一个对SIGCHLD的排队机制。我一直在大型的项目中用这个,很不错。

论坛徽章:
0
4 [报告]
发表于 2006-09-15 16:08 |只看该作者
你能给出一简短的例子引起你说的那个问题的程序?

论坛徽章:
0
5 [报告]
发表于 2006-09-15 16:36 |只看该作者
我的看法,不一定对啊,呵呵.先看看下面的程序.


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <signal.h>
  4. #include <sys/types.h>
  5. #include <sys/wait.h>

  6. void sig_child(int signo)
  7. { pid_t pid;
  8. int stat;
  9. while( (pid = waitpid(-1,&stat,WNOHANG)) > 0)
  10. {
  11. printf("child %d exit\n",pid);
  12. sleep(5);//这应该导致信号丢失吧?
  13. }
  14. return;
  15. }

  16. void child_func()
  17. {
  18. return;
  19. }

  20. int main()
  21. {
  22. pid_t pid;
  23. int i = 0;

  24. signal(SIGCHLD,sig_child);
  25. for(;i < 5;i ++)
  26. {
  27. if( (pid = fork()) == 0)
  28. {
  29. child_func();
  30. printf("child function finished\n");
  31. exit(0);
  32. }
  33. else if(pid > 0)
  34. {
  35. continue;
  36. }
  37. else
  38. {
  39. printf("fork failed\n");
  40. exit(1);
  41. }
  42. }
  43. return 0;
  44. }

复制代码


linux:~/test # gcc -o waitpid waitpid.c
linux:~/test # ./waitpid
child function finished
child 7449 exit
child function finished
child 7450 exit
child function finished
child 7454 exit
child function finished
child 7455 exit
child function finished
child 7459 exit

对于SIGCHILD信号(属于不可靠信号,不支持信号排队.),按理说应该有信号丢失,可为什么还是输出5次呢?这实际上没有把握清楚waitpid(-1,&stat,WNOHANG)函数的作用.它是用来用来检测进程是否已结束并回收僵尸进程的,在这个程序里信号确实会丢失的.但waitpid函数不是由SIGCHILD信号驱动的.

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
6 [报告]
发表于 2006-09-15 16:51 |只看该作者
丢失了怕什么。
while(waitpid()) 是个循环,只要下次不丢失,照样会把以前丢失了的都一起回收的嘛!
不然也就不会写成一个循环了。
写成循环的原因,就是怕丢失。

论坛徽章:
0
7 [报告]
发表于 2006-09-15 16:59 |只看该作者
to susesuse:
不太同意你的看法, 这是个本来就很难重现的问题, 不能因为只举个例子就推出结论.
我想问你当父进程正在执行sigchld的信号处理程序, 内核这时向父进程发送一个sigchld,
因为sigchld是不可靠信号,进程就丢弃这个信号.既然丢弃,就是说父进程没有进行sigchld信号处理,那不就会产生僵尸进程了吗?
不知道我的理解对不对?
谢谢linternt

论坛徽章:
0
8 [报告]
发表于 2006-09-15 17:02 |只看该作者
愚钝,不太明白flw的意思,既然丢了,是怎么找回来的.执教

论坛徽章:
0
9 [报告]
发表于 2006-09-15 17:15 |只看该作者
不知道linternt可不可以贴一下代码!

论坛徽章:
0
10 [报告]
发表于 2006-09-15 17:16 |只看该作者
这也基本是个伪命题。不存在丢失,还有排队的问题
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP