免费注册 查看新帖 |

Chinaunix

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

关于使用管道实现父进程监听子进程状态的疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-06-03 01:31 |只看该作者 |倒序浏览
最近看了一段使用管道实现父进程监听子进程状态的代码,具体实现
方法如下:

  1. #include <stdio.h>;
  2. #include <stdlib.h>;
  3. #include <fcntl.h>;
  4. #include <unistd.h>;
  5. #include <sys/types.h>;

  6. void main()
  7. {
  8.     pid_t        pid;
  9.     int            fd[2],  nfds,  retcode;
  10.     fd_set      rdst;

  11.     if (pipe(fd) < 0)
  12.        printf("pipe error!\n");
  13.     pid = fork();
  14.     switch (pid)
  15.     {
  16.     case  -1:
  17.                   close(fd[0]);
  18.                   close(fd[1]);
  19.                   printf("fork error!\n);
  20.                   break;
  21.     case   0:
  22.                   close(fd[1]);
  23.                   do_something();
  24.                   break;
  25.     default:
  26.                   close(fd[0]);
  27.                   nfds = fd[1];
  28.                   FD_ZERO(&rdst);
  29.                   FD_SET(fd[1], &rdst);
  30.                   nfds++;
  31.                   retcode = select(nfds, &rdst, NULL, NULL, NULL);
  32.                   if (retcode >; 0)
  33.                   {
  34.                        if (FD_ISSET(fd[1], &rdst))
  35.                            printf("child process has exit!\n");
  36.                   }
  37.                   break;
  38.     }
  39.     return ;
  40. }
复制代码


有一点不明白的是为何当子进程退出后,父进程的fd[1]描述符的状态会发生改变。请高手指点一下。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
2 [报告]
发表于 2003-06-03 12:25 |只看该作者

关于使用管道实现父进程监听子进程状态的疑问

1、分析:
如上代码fork前pipe一个管道,fork后子进程关闭写的一段,父进程关闭读的一段。

看代码
nfds = fd[1];
                  FD_ZERO(&rdst);
                  FD_SET(fd[1], &rdst);
父进程用select监测rdst。rdst被设置为管道可写。

然而 select中
retcode = select(nfds, &rdst, NULL, NULL, NULL);
却又监测可读。

代码混乱。

2、结论:
以如上代码为例子,父进程用select测试fd[0]可读。得不到任何消息。

父进程用select测试fd[1]可写。可以得到消息。但是必须保证子进程相pipe中写了东西,或者子进程exit或异常(如core)退出。这个结论的前提时select跟改为监测写。

论坛徽章:
0
3 [报告]
发表于 2003-06-03 16:15 |只看该作者

关于使用管道实现父进程监听子进程状态的疑问

标准的pipe,fd[0]为读,fd[1]为写。某些系统,如solaris其fd[0]和fd[1]同时打开为读写。
楼主的代码应该是想用管道的EOF来通知父进程。

论坛徽章:
0
4 [报告]
发表于 2003-06-03 19:39 |只看该作者

关于使用管道实现父进程监听子进程状态的疑问

[quote]原帖由 "蓝色键盘"]可以得到消息。但是必须保证子进程相pipe中写了东西,或者子进程exit或异常(如core)退出。这个结论的前提时select跟改为监测写。[/quote 发表:
     

看来版主也不是很清楚这种用法。上述的代码在solaris和FreeBSD上都可以运行,并且父进程确实可以检测到子进程的退出。我不明白这种用法为什么可以检测到子进程的退出,所以才来这里请教,可是却落了个代码混乱,真的没有人见过这种用法吗?     

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
5 [报告]
发表于 2003-06-03 20:41 |只看该作者

关于使用管道实现父进程监听子进程状态的疑问

我觉得fireryfox说的对。补充一点,你把父进程中的0互换1是一样的,结果是一样的。

从通常管道操作的角度来说,fd[1]是不允许读的,从这个角度来说,键盘说的是正确地,所以,如果我来写,会把1改成0,不会让人混淆(rset).

论坛徽章:
0
6 [报告]
发表于 2003-06-03 21:28 |只看该作者

关于使用管道实现父进程监听子进程状态的疑问

我觉得可能大家没仔细看代码,代码主要目的是在管道方向为从父进程到子进程时,如果子进程仍然存在,父进程select调用会阻塞,子进程退出后,父进程的select调用才会返回,如果把0和1互换,就不会起到这个作用了。
       问题是为什么子进程退出后描述符fd[1]的状态会发生改变?在通常管道的用法中,描述符fd[1]是不允许读的,但代码中的用法却是我头一次看到的。fieryfox认为代码是通过管道的EOF来通知父进程,但是这个EOF是怎么产生的呢,这时管道的方向是从父进程到子进程。
       如果把管道的方向改为从子进程到父进程,判断描述符fd[0]是否为读已准备,可能就不会产生歧义了,但是在这种情况下,为什么父进程的select调用也会阻塞呢?

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
7 [报告]
发表于 2003-06-03 21:44 |只看该作者

关于使用管道实现父进程监听子进程状态的疑问

呵呵,你测试过了么?

测试完,再下结论。例子不一定正确。

至少,在linux上,我的补充和判断是正确的。

进程退出的时候,会关闭所有的文件描述符,所以产生EOF。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
8 [报告]
发表于 2003-06-03 21:46 |只看该作者

关于使用管道实现父进程监听子进程状态的疑问

刚才在solaris上测试,也是一样

论坛徽章:
0
9 [报告]
发表于 2003-06-03 21:53 |只看该作者

关于使用管道实现父进程监听子进程状态的疑问

原帖由 "gadfly" 发表:
呵呵,你测试过了么?

测试完,再下结论。例子不一定正确。

至少,在linux上,我的补充和判断是正确的。

进程退出的时候,会关闭所有的文件描述符,所以产生EOF。
   

我是测试过代码后才在这里提出问题的,测试在solaris和FreeBSD上都通过了,linux上我没有试过,另外你提出的将父进程中的0和1互换,是什么意思呢?是指的将FD_SET(fd[1], &rdst) 改为FD_SET(fd[0], &rdst), 将FD_ISSET(fd[1], &rdst)改为FD_ISSET(fd[0], &rdst)吗?这样做在管道方向为从父进程到子进程时,父进程不会在select调用阻塞的,会直接退出的。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
10 [报告]
发表于 2003-06-03 22:09 |只看该作者

关于使用管道实现父进程监听子进程状态的疑问

大概明白你的意思了。你的意思就是说,是父通过管道写数据到子,同时有检测子的退出,对不对?

这不失为一种方法。

但是我觉得如果select仅仅用来检测子的退出,就没必要了,因为,
1.如果子主动关闭fd0,select也会退出。这种方法,你判断不了是否退出
2.父write(fd...),在子关闭fd0或退出的情况下是会出错的,同样可以起到这种作用。
3.何况,还有SIGCHLD可以起作用
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP