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

xiaoxiao2021-02-28  60

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

[cpp]  view plain  copy #include <stdio.h>  #include <signal.h>  #include <unistd.h>  #include <sys/types.h>  #include <sys/wait.h>  #include <stdlib.h>    volatile int wait_flag=0;    void change_value(int para);  void stop_info(int para);    int main()  {      int pid1,pid2;      signal(2,stop_info);        wait_flag = 1;        printf("before fork child1\n");      while((pid1=fork())<0);      printf("after fork child1\n");        if(pid1>0)      {          while((pid2=fork())<0);            if(pid2>0)          {              printf("parent id is %d\n",getpid());              wait(0);              wait(0);              printf("parent is killed.\n");              exit(0);          }          else          {              signal(17,change_value);              printf("child2 id is %d\n",getpid());              while(wait_flag == 1);              printf("child2 is killed\n");              exit(0);          }      }      else      {          signal(16,change_value);          printf("child1 id is %d\n",getpid());          while(wait_flag == 1);          printf("child1 is killed\n");          exit(0);      }  }    void change_value(int para)  {      wait_flag = 0;      printf("pid: %d, wait_flag = 0\n",getpid());  }      void stop_info(int para)  {      printf("process %d: stop info!\n",getpid());  }  

下面是一个结果:

[cpp]  view plain  copy > gcc -Wall fork.c -o fork  > ./fork   before fork child1  after fork child1  after fork child1  parent id is 7118  child1 id is 7119  child2 id is 7120  

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

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

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

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

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

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

不过, 值得注意的是,

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

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

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

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

[cpp]  view plain  copy process 7119: stop info!   按照程序,向子进程1发信号  kill -16 7119

[cpp]  view plain  copy pid: 7119, wait_flag = 0  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 pid: 7120, wait_flag = 0  child2 is killed  parent is killed.   直到这里,子进2的wait_flag变为0,然后死掉,接着等待它们结束的父进程死掉,至此程序结束。

结合书中的解释:

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

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

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

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

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

转载请注明原文地址: https://www.6miu.com/read-2350026.html

最新回复(0)