转载: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函数估计也是一样,不清楚其中的原理,不好解释。