Linux fork,signal多进程间信号例子

转载:http://blog.csdn.net/woyaozuo2012/article/details/12133649

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <signal.h>  
  3. #include <unistd.h>  
  4. #include <sys/types.h>  
  5. #include <sys/wait.h>  
  6. #include <stdlib.h>  
  7.   
  8. volatile int wait_flag=0;  
  9.   
  10. void change_value(int para);  
  11. void stop_info(int para);  
  12.   
  13. int main()  
  14. {  
  15.     int pid1,pid2;  
  16.     signal(2,stop_info);  
  17.   
  18.     wait_flag = 1;  
  19.   
  20.     printf("before fork child1\n");  
  21.     while((pid1=fork())<0);  
  22.     printf("after fork child1\n");  
  23.   
  24.     if(pid1>0)  
  25.     {  
  26.         while((pid2=fork())<0);  
  27.   
  28.         if(pid2>0)  
  29.         {  
  30.             printf("parent id is %d\n",getpid());  
  31.             wait(0);  
  32.             wait(0);  
  33.             printf("parent is killed.\n");  
  34.             exit(0);  
  35.         }  
  36.         else  
  37.         {  
  38.             signal(17,change_value);  
  39.             printf("child2 id is %d\n",getpid());  
  40.             while(wait_flag == 1);  
  41.             printf("child2 is killed\n");  
  42.             exit(0);  
  43.         }  
  44.     }  
  45.     else  
  46.     {  
  47.         signal(16,change_value);  
  48.         printf("child1 id is %d\n",getpid());  
  49.         while(wait_flag == 1);  
  50.         printf("child1 is killed\n");  
  51.         exit(0);  
  52.     }  
  53. }  
  54.   
  55. void change_value(int para)  
  56. {  
  57.     wait_flag = 0;  
  58.     printf("pid: %d, wait_flag = 0\n",getpid());  
  59. }  
  60.   
  61.   
  62. void stop_info(int para)  
  63. {  
  64.     printf("process %d: stop info!\n",getpid());  
  65. }  

下面是一个结果:

[cpp]  view plain  copy
  1. > gcc -Wall fork.c -o fork  
  2. > ./fork   
  3. before fork child1  
  4. after fork child1  
  5. after fork child1  
  6. parent id is 7118  
  7. child1 id is 7119  
  8. child2 id is 7120  

程序会停在这里,注意:before fork child1 打印了一次,after fork child1打印了两次

也就是说fork函数前的代码只会在父进程中执行一次


按下Ctrl + C后程序并不会退出,并出现如下:

[cpp]  view plain  copy
  1. ^Cprocess 7118: stop info!  
  2. process 7119: stop info!  
  3. process 7120: stop info!  

这是自然的,因为程序重新定义了停止信号:

[cpp]  view plain  copy
  1. signal(2,stop_info);  

不过, 值得注意的是,

(1)Ctrl + C是向进程及其所有的子进程发送停止信号,而不止是它自己这个进程。

(2)这个函数定义在fork之前,从结果看两个子进程明显均执行了这个函数,

          然而,前面已提到,fork函数之前的printf函数却只会由父进程执行一次。


当然,可以另开一个终端,用kill单独地向某一个进程发信号: kill -2 7119

[cpp]  view plain  copy
  1. process 7119: stop info!  

按照程序,向子进程1发信号  kill -16 7119

[cpp]  view plain  copy
  1. pid: 7119, wait_flag = 0  
  2. child1 is killed  

这里wait_flag已变为0,只死掉了子进程1,但是子进程2并没有死掉,可见,三个进程的wait_flag是独立的,尽管它是个全局变量

同样需要注意,wait_flag = 1语句在fork之前,这明显三个进程都执行过它, 否则,两个子进程会因为wait_flag = 0而立即退出。

问题来了:为什么printf函数却只执行一遍呢?


向子进程2发信号 kill -17 7120

[cpp]  view plain  copy
  1. pid: 7120, wait_flag = 0  
  2. child2 is killed  
  3. parent is killed.  

直到这里,子进2的wait_flag变为0,然后死掉,接着等待它们结束的父进程死掉,至此程序结束。



结合书中的解释:

fork函数被调用一次,但返回两次,子进程和父进程继续执行fork调用之后的函数,子进程是是父进程的副本,

获得父进程的数据空间、堆、栈的副本,但并不共享这些存储空间部分,只共享正文段。


所以,以上的解释是错误的,wait_flag=1只由父进程执行一次, 也就是说,子进程获得副本时,

wait_flag已经变为1。所以,更准确地说,子进程获得的副本,是父进程当前状态的副本。

signal函数估计也是一样,不清楚其中的原理,不好解释。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值