免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5538 | 回复: 7

[C] 一个父子进程信号通信的小程序 [复制链接]

论坛徽章:
0
发表于 2008-04-02 11:09 |显示全部楼层
小弟新手, 写了一个父子进程信号通信的小程序, 运行的时候有点问题,请大家帮忙看看

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <signal.h>
  9. #include <sys/uio.h>
  10. #include <sys/wait.h>
  11. #include <sys/errno.h>

  12. #define MAXCNT 4

  13. void sig_usr(int signo)
  14. {
  15.         if( signo == SIGCONT)
  16.                 printf("received SIGCONT\n");
  17.         else
  18.                 printf("received unexpected signal(%d)\n", signo);

  19.         return;
  20. }

  21. int main(void)
  22. {
  23.         int idx = 0;
  24.         int status;

  25.         pid_t pid;

  26.         if( (pid=fork()) < 0 ) {
  27.                 printf("fork error\n");
  28.                 exit(1);
  29.         }else if (pid == 0) {                   /* child */
  30.                 while( idx < MAXCNT ) {
  31.                         if( signal(SIGCONT, sig_usr) == SIG_ERR ) {
  32.                                 printf("c signal error\n");
  33.                                 exit(2);
  34.                         }
  35.                         printf("child[%d]\n", idx);
  36.                         fflush(stdout);
  37.                         if( idx < MAXCNT - 1 ){
  38.                                 printf("child pause ...\n");
  39.                                 fflush(stdout);
  40.                                 kill(getppid(), SIGCONT);
  41.                                 pause();
  42.                         }
  43.                         printf("child up ...\n");
  44.                         fflush(stdout);
  45.                         idx++;
  46.                 }
  47.                 exit(99);
  48.         }else {                                 /* parent */
  49.                 while( idx < MAXCNT ) {
  50.                         if( signal(SIGCONT, sig_usr) == SIG_ERR ) {
  51.                                 printf("p signal error\n");
  52.                                 exit(3);
  53.                         }
  54.                         printf("parent[%d]\n", idx);
  55.                         fflush(stdout);
  56.                         kill(pid, SIGCONT);
  57.                         if( idx < MAXCNT - 1 ) {
  58.                                 printf("parent pause ...\n");
  59.                                 fflush(stdout);
  60.                                 kill(pid, SIGCONT);
  61.                                 pause();
  62.                         }
  63.                         printf("parent up ...\n");
  64.                         fflush(stdout);
  65.                         idx++;
  66.                 }
  67.                 if( waitpid(pid, &status, 0) < 0 ) {
  68.                         printf("waitpid error\n");
  69.                         exit(3);
  70.                 }
  71.         }
  72.         return 0;
  73. }
复制代码


编译: gcc -Wall -O2 -o test test.c
运行: ./test


  1. [root@linux /home/test]./test
  2. child[0]
  3. child pause ...
  4. parent[0]
  5. parent pause ...
  6. received SIGCONT
  7. child up ...
  8. child[1]
  9. child pause ...
  10. received SIGCONT
  11. parent up ...
  12. parent[1]
  13. parent pause ...
  14. received SIGCONT
  15. child up ...
  16. child[2]
  17. child pause ...
  18. received SIGCONT
  19. parent up ...
  20. parent[2]
  21. parent pause ...
  22. received SIGCONT                          <=== seemed hang here

复制代码


父进程在等待之后发送 SIGCONT, 子进程没有 up,  CTRL+Z stop进程之后, fg 在运行它又成功了. 希望大家帮忙分析一下, 谢谢!

论坛徽章:
0
发表于 2008-04-02 11:23 |显示全部楼层

  1. [root@linux test]# ./test
  2. child[0]
  3. child pause ...
  4. parent[0]
  5. parent pause ...
  6. received SIGCONT
  7. child up ...
  8. child[1]
  9. child pause ...
  10. received SIGCONT
  11. parent up ...
  12. parent[1]
  13. parent pause ...
  14. received SIGCONT
  15. child up ...
  16. child[2]
  17. child pause ...
  18. received SIGCONT
  19. parent up ...
  20. parent[2]
  21. parent pause ...
  22. received SIGCONT

  23. [1]+  Stopped                 ./test                            <=== CTRL+Z

  24. [root@linux test]# fg
  25. ./test
  26. received SIGCONT
  27. parent up ...
  28. parent[3]
  29. parent up ...
  30. received SIGCONT
  31. child up ...
  32. child[3]
  33. child up ...
  34. [root@linux test]# echo $?
  35. 0
  36. [root@linux test]#
复制代码

论坛徽章:
24
15-16赛季CBA联赛之北京
日期:2018-08-17 18:43:33技术图书徽章
日期:2018-08-22 12:53:57技术图书徽章
日期:2018-08-22 12:54:20技术图书徽章
日期:2018-08-22 12:54:3015-16赛季CBA联赛之福建
日期:2018-10-19 16:58:1619周年集字徽章-庆
日期:2019-08-27 13:28:5619周年集字徽章-19
日期:2019-08-27 13:31:2619周年集字徽章-19
日期:2019-08-27 13:31:2615-16赛季CBA联赛之同曦
日期:2019-09-05 12:03:2819周年集字徽章-周
日期:2019-09-06 18:54:5415-16赛季CBA联赛之上海
日期:2018-07-25 11:55:2615-16赛季CBA联赛之青岛
日期:2018-07-10 14:13:18
发表于 2008-04-02 15:09 |显示全部楼层
能不能试一试用别的信号呢? 比如用户自定义那几个.

论坛徽章:
0
发表于 2008-04-02 16:50 |显示全部楼层
程序执行流程的问题。有时候会出现这种情况:

父进程还没挂起,子进程就给它发SIGCOUT信号,当它挂起时,却等不到子进程的
SIGCOUT信号,因为此时子进程也在等待父进程的信号,这样系统就处于一种死锁的状态了。

具体的问题也就是, signal注册信号和pause挂起之间有个时间窗口,在这个窗口内信号已经
发生过,程序当然就一直处于pause状态了。

论坛徽章:
0
发表于 2008-04-02 17:17 |显示全部楼层

回复 #3 incle 的帖子

SIGCONT 信号系统默认的处理方式可以对付这个
SIGUSR1, SIGUSR2 还要在去定义

论坛徽章:
0
发表于 2008-04-02 17:20 |显示全部楼层

回复 #4 G00GLE 的帖子


  1. child up ...
  2. child[2]
  3. child pause ...            <= child pause
  4. received SIGCONT     <= parent received
  5. parent up ...
  6. parent[2]
  7. parent pause ...
  8. received SIGCONT     <= child received                   <=== seemed hang here
复制代码


child 已经挂起了, 然后在收到的父进程的SIGCONT 信号的

论坛徽章:
0
发表于 2008-04-02 19:19 |显示全部楼层
这时候应该使用可靠信号语义实现,用pause有竞争。
man sigsuspend
man sigprocmask

论坛徽章:
0
发表于 2008-04-03 18:26 |显示全部楼层

回复 #7 JohnBull 的帖子

谢谢版主提示, 我对上面的程序做了修改,大致能运行正确了, 父子进程互相传递信号, 交替打印


  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>
  8. #include <signal.h>
  9. #include <sys/uio.h>
  10. #include <sys/wait.h>
  11. #include <sys/errno.h>

  12. #define MAXCNT 4

  13. volatile sig_atomic_t    contflag;    /* set nonzero by signal handler */

  14. void sig_usr(int signo)
  15. {
  16.         if( signo == SIGCONT) {
  17.                 contflag = 1;
  18.                 printf("received SIGCONT\n");
  19.         } else
  20.                 printf("received unexpected signal(%d)\n", signo);

  21.         return;
  22. }

  23. int main(void)
  24. {
  25.         int idx = 0;
  26.         int status;
  27.         pid_t pid;

  28.         sigset_t newmask;
  29.         sigset_t oldmask;
  30.         sigset_t zeromask;

  31.         sigemptyset(&zeromask);
  32.         sigemptyset(&newmask);
  33.         sigaddset(&newmask, SIGCONT);
  34.         if( (pid=fork()) < 0 ) {
  35.                 printf("fork error\n");
  36.                 exit(1);
  37.         }else if (pid == 0) {                   /* child */
  38.                 while( idx < MAXCNT ) {
  39.                         if( signal(SIGCONT, sig_usr) == SIG_ERR ) {
  40.                                 printf("c signal error\n");
  41.                                 exit(2);
  42.                         }
  43.                         if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
  44.                                 printf("SIG_BLOCK error\n");
  45.                                 exit(1);
  46.                         }
  47.                         printf("child[%d]\n", idx);
  48.                         printf("child pause ...\n");
  49.                         kill(getppid(), SIGCONT);
  50.                         while( contflag == 0)
  51.                                 sigsuspend(&zeromask);
  52.                         printf("child up ...\n");
  53.                         contflag = 0;
  54.                         if( sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0 ) {
  55.                                 printf("SIG_SETMASK error\n");
  56.                                 exit(2);
  57.                         }
  58.                         idx++;
  59.                 }
  60.                 kill(getppid(), SIGCONT);       /* child done */
  61.                 exit(99);
  62.         }else {                                 /* parent */
  63.                 while( idx < MAXCNT ) {
  64.                         if( signal(SIGCONT, sig_usr) == SIG_ERR ) {
  65.                                 printf("p signal error\n");
  66.                                 exit(3);
  67.                         }
  68.                         if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
  69.                                 printf("SIG_BLOCK error\n");
  70.                                 exit(3);
  71.                         }
  72.                         printf("parent pause ...[%d]\n", idx);
  73.                         kill(pid, SIGCONT);
  74.                         while( contflag == 0)
  75.                                 sigsuspend(&zeromask);
  76.                         printf("parent up ...\n");
  77.                         contflag = 0;
  78.                         if( sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0 ) {
  79.                                 printf("SIG_SETMASK error\n");
  80.                                 exit(3);
  81.                         }
  82.                         idx++;
  83.                 }
  84.                 if( waitpid(pid, &status, 0) < 0 ) {
  85.                         printf("waitpid error\n");
  86.                         exit(3);
  87.                 }
  88.         }
  89.         return 0;
  90. }

复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP