免费注册 查看新帖 |

Chinaunix

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

关于fork,wait的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-05-19 20:36 |只看该作者 |倒序浏览
问题描述很简单,写一个程序接收整数,根据该整数创立若干个进程,sleep一段时间,然后父进程报告每个子进程的退出。
我的代码有个问题我无法理解。先把正确的代码贴出来:
  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include <stdlib.h>


  4. int wait_pid=0;

  5. int main(int args,char *av[])
  6. {
  7.         //signal(SIGCHLD,report_quit);
  8.         if(args==1)
  9.         {
  10.                 printf("You should declare the number of the child process that you want to build!");
  11.                 return 1;
  12.         }
  13.         else
  14.         {
  15.                 int num_p=atoi(av[1]);
  16.                 int child_pid=1;
  17.                 int i=0;
  18.                 for(i=0;i<num_p;i++)
  19.                 {
  20.                         if(child_pid!=0)
  21.                         {
  22.                                 child_pid=fork();
  23.                                 printf("%d :%d \n",getpid(),child_pid);
  24.                                 if(child_pid==0)
  25.                                 {
  26.                                         sleep(2);
  27.                                         exit(17);
  28.                                 }
  29.                                 else if(child_pid==-1)
  30.                                 {
  31.                                         perror("fork error!");
  32.                                         exit(2);
  33.                                 }
  34.                         }
  35.                 }
  36.                 while((wait_pid=wait(NULL))!=-1)
  37.                         printf("the child process %d exited!\n",wait_pid);
  38.         }
  39.         return 0;
  40. }
复制代码
执行结果是:
  1. 11240 :11241
  2. 11241 :0
  3. 11240 :11242
  4. 11242 :0
  5. 11240 :11243
  6. 11243 :0
  7. 11240 :11244
  8. 11244 :0
  9. the child process 11241 exited!
  10. the child process 11242 exited!
  11. the child process 11243 exited!
  12. the child process 11244 exited!
复制代码
而我想利用信号处理的方法:子进程结束时,调用exit时会向父进程发送一个SIGCHLD信号,让父进程捕捉这个信号来报告子进程的结束。代码中加入了一个处理函数:
  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include <stdlib.h>

  4. void report_quit();
  5. int wait_pid=0;

  6. int main(int args,char *av[])
  7. {
  8.         signal(SIGCHLD,report_quit);
  9.         if(args==1)
  10.         {
  11.                 printf("You should declare the number of the child process that you want to build!");
  12.                 return 1;
  13.         }
  14.         else
  15.         {
  16.                 int num_p=atoi(av[1]);
  17.                 int child_pid=1;
  18.                 int i=0;
  19.                 for(i=0;i<num_p;i++)
  20.                 {
  21.                         if(child_pid!=0)
  22.                         {
  23.                                 child_pid=fork();
  24.                                 printf("%d :%d \n",getpid(),child_pid);
  25.                                 if(child_pid==0)
  26.                                 {
  27.                                         sleep(2);
  28.                                         exit(17);
  29.                                 }
  30.                                 else if(child_pid==-1)
  31.                                 {
  32.                                         perror("fork error!");
  33.                                         exit(2);
  34.                                 }
  35.                         }
  36.                 }
  37.                 while(1)
  38.                         wait_pid=wait(NULL);
  39.                        // printf("the child process %d exited!\n",wait_pid);
  40.         }
  41.         return 0;
  42. }

  43. void report_quit()
  44. {
  45.         printf("the child process %d exited.\n",wait_pid);
  46. }
复制代码
但是执行结果如下:
  1. 11266 :11267
  2. 11267 :0
  3. 11266 :11268
  4. 11268 :0
  5. 11266 :11269
  6. 11269 :0
  7. 11266 :11270
  8. 11270 :0
  9. the child process 0 exited.
  10. the child process 11268 exited.
  11. the child process 11268 exited.
复制代码
我不明白为什么了。如果您知道,请讲一下,非常感谢。

论坛徽章:
1
戌狗
日期:2014-07-17 19:24:40
2 [报告]
发表于 2012-05-19 21:53 |只看该作者
本帖最后由 kprc 于 2012-05-19 21:56 编辑

这个能编译通过?
凌乱了,变量定义规范一些行不,全局变量前面加个G,小G的G好不?

论坛徽章:
0
3 [报告]
发表于 2012-05-19 23:07 |只看该作者
印象中应该是 wait 系统调用的问题,记不太清了,回头翻下红宝书。。。

论坛徽章:
0
4 [报告]
发表于 2012-05-20 09:30 |只看该作者
kprc 发表于 2012-05-19 21:53
这个能编译通过?
凌乱了,变量定义规范一些行不,全局变量前面加个G,小G的G好不?

非常感谢您的建议。

论坛徽章:
0
5 [报告]
发表于 2012-05-20 10:05 |只看该作者
luoyan_xy 发表于 2012-05-19 23:07
印象中应该是 wait 系统调用的问题,记不太清了,回头翻下红宝书。。。

红宝书是什么啊?

论坛徽章:
0
6 [报告]
发表于 2012-05-20 10:25 |只看该作者
你的信号处理器里边应该调用一下wait吧,不然如何得知是哪个子进程结束了,wait_pid是全局变量

另外,最后那个while(1)有啥用,没看明白呵呵

论坛徽章:
1
戌狗
日期:2014-07-17 19:24:40
7 [报告]
发表于 2012-05-21 09:23 |只看该作者
将你的例子改了一下,验证了一下。
while(1)
{
                        wait_pid=wait(NULL);
                        printf("wait the child process %d exited!\n",wait_pid);  /*与report_quit区分开*/
                        if(-1 == wait_pid)
                        {
                               break;
                        }
}
打印的结果:
the child process 0 exited.    ------2427发出的信号,但这个时候wait还没有得到2427的pid,所以打印是这个样子的。
wait the child process 2427 exited!   ---wait得到了,并打印了正确的。
the child process 2427 exited.       ------同理wait还未得到2426
wait the child process 2426 exited!
the child process 2426 exited.
wait the child process 2428 exited!
the child process 2428 exited.
wait the child process 2425 exited!
wait the child process -1 exited!

进程在转到zombile的时候才会被wait捕获,
在转到zombile前,会发出exit的信号。







论坛徽章:
0
8 [报告]
发表于 2012-05-21 20:50 |只看该作者
建议你把
  1. while(1)
  2.                         wait_pid=wait(NULL);
  3.                        // printf("the child process %d exited!\n",wait_pid);
复制代码
换成
  1. while(wait_pid != -1)
  2.                         wait_pid=wait(NULL);
  3.                        // printf("the child process %d exited!\n",wait_pid);
复制代码
然后放到, signal handler 里面。

论坛徽章:
0
9 [报告]
发表于 2012-05-22 20:11 |只看该作者
信号处理函数report_quit的原型不对吧,应该有一个整数的输入参数。

论坛徽章:
0
10 [报告]
发表于 2012-05-22 20:21 |只看该作者
之所以输出
“the child process 0 exited.
the child process 11268 exited.
the child process 11268 exited.”
原因是:
第一次wait的时候,父进程处于等待状态,这时wait_id还是0,如果这时有第一个子进程结束了,那么信号处理函数立马被调用并打印出第一条结果。注意这时wait_id还是0。
随后wait返回第一个子进程的id。
然后父进程等待第二个子进程的结束,如果第二个子进程结束了,但是这时调用report_quit时,wait_id记录的是上一次的id,所以输出的是第一个子进程的id。
依次往后。

但是,你的while(1) 写的不漂亮吧,死循环啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP