免费注册 查看新帖 |

Chinaunix

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

使用信号进行父子进程同步,对结果重定向后出错。肯请高手解答 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-07 15:39 |只看该作者 |倒序浏览
20可用积分
本帖最后由 j3kljs02398j 于 2011-12-07 15:41 编辑

问题描述:
使用信号对两个进程进行同步, 正常输出,结果没有问题,但是对输出进行重定向后,结果就错了。

正常输出:
  1. $: ./tellwait
  2. parent        :  1
  3. child        :  2
  4. parent        :  3
  5. child        :  4
  6. parent        :  5
  7. child        :  6
  8. parent        :  7
  9. child        :  8
  10. parent        :  9
  11. child        : 10
  12. #正常结果应该是父子进程交替对一共享变量加1
复制代码
对结果进行重定向:
  1. $: /tellwait > tellwait.txt
  2. $:  cat tellwait.txt
  3. child        :  2
  4. child        :  4
  5. child        :  6
  6. child        :  8
  7. child        : 10
  8. parent        :  1
  9. parent        :  3
  10. parent        :  5
  11. parent        :  7
  12. parent        :  9
  13. #重定向后,输出不是交替进行了,why?
复制代码
源代码:
  1. /*
  2. * =====================================================================================
  3. *
  4. *       Filename:  tellwait.c
  5. *
  6. *    Description:  使用信号进行多个进程同步
  7. *                父子进程交叉对共享变量加一,输出结果
  8. *
  9. *        Version:  1.0
  10. *        Created:  2011年12月06日 10时48分41秒
  11. *       Compiler:  gcc
  12. *       Platform:  Linux .6.32-35-generic i686 GNU/Linux
  13. *
  14. * =====================================================================================
  15. */
  16. #include <assert.h>
  17. #include <stdio.h>
  18. #include <unistd.h>
  19. #include <signal.h>
  20. #include <sys/mman.h>
  21. #include <sys/wait.h>

  22. #define NUM (5 * 2)

  23. void
  24. sig_usr(int signo)
  25. {
  26.         if (signo == SIGUSR1 || signo == SIGUSR2)
  27.                 ;
  28. }

  29. int main(void)
  30. {
  31.         int *shared_p;
  32.         pid_t pid;
  33.         int i;
  34.         struct sigaction act1;
  35.         struct sigaction act2;

  36.         /* 捕获SIGUSR1,SIGUSR2 */
  37.         act1.sa_handler = sig_usr;
  38.         sigfillset(&act1.sa_mask);
  39.         act1.sa_flags = 0;

  40.         act2.sa_handler = sig_usr;
  41.         sigemptyset(&act2.sa_mask);
  42.         act2.sa_flags = 0;

  43.         sigaction(SIGUSR1, &act1, NULL);
  44.         sigaction(SIGUSR2, &act2, NULL);

  45.         /* 共享一个一块数据,供父子进程读写 */
  46.         shared_p = (int *) mmap(NULL, sizeof(int), PROT_READ |PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  47.         assert(shared_p != NULL);
  48.         *shared_p = 0;

  49.         pid = fork();
  50.         if (pid < 0) {
  51.                 perror("fork");
  52.                 return -1;
  53.         }
  54.         else if (pid == 0) {
  55.                 sigset_t set2, old;
  56.                 /* 子进程收到SIGUSR2信号时对共享变量操作 */
  57.                 sigemptyset(&set2);
  58.                 sigaddset(&set2, SIGUSR2);
  59.                 sigprocmask(SIG_BLOCK, &set2, &old);
  60.                 sigdelset(&old, SIGUSR2);

  61.                 for (i = 0; i < NUM / 2; ++i) {/* 简单加1 */
  62.                         sigsuspend(&old);
  63.                         (*shared_p)++;
  64.                         printf("child\t: %2d\n", *shared_p);
  65.                         kill(getppid(), SIGUSR1);
  66.                 }
  67.         }
  68.         else {
  69.                 sigset_t set1, old;

  70.                 /* 父进程收到SIGUSR1信号时对共享变量操作 */
  71.                 sigemptyset(&set1);
  72.                 sigaddset(&set1, SIGUSR1);
  73.                 sigprocmask(SIG_BLOCK, &set1, &old);
  74.                 sigdelset(&old, SIGUSR1);
  75.                 for (i = 0; i < NUM / 2; ++i) {/* 简单加1 */
  76.                         (*shared_p)++;
  77.                         printf("parent\t: %2d\n", *shared_p);
  78.                         kill(pid, SIGUSR2);
  79.                         sigsuspend(&old);
  80.                 }
  81.                 wait(NULL);
  82.                 munmap(shared_p, sizeof (int));
  83.         }       
  84.         return 0;
  85. }
复制代码

最佳答案

查看完整内容

没有重定向的时候,默认输出到标准输出,是行缓冲的。重定向后,变成了全缓冲。可以在每次printf后面刷新缓冲区,或者改用write。

论坛徽章:
0
2 [报告]
发表于 2011-12-07 15:39 |只看该作者
没有重定向的时候,默认输出到标准输出,是行缓冲的。重定向后,变成了全缓冲。可以在每次printf后面刷新缓冲区,或者改用write。

论坛徽章:
0
3 [报告]
发表于 2011-12-08 18:05 |只看该作者
没有重定向的时候,默认输出到标准输出,是行缓冲的。重定向后,变成了全缓冲。可以在每次printf后面刷新缓冲区,或者改用write。

论坛徽章:
0
4 [报告]
发表于 2011-12-10 14:30 |只看该作者
确实如此。非常感谢!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP