linux小实验(3)---fork、signal


#include 
#include 
#include 
#include 
#include 
#include 

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());
}



下面是一个结果:

> 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后程序并不会退出,并出现如下:

^Cprocess 7118: stop info!
process 7119: stop info!
process 7120: stop info!

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

signal(2,stop_info);

不过, 值得注意的是,

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

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

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


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

process 7119: stop info!

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

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

pid: 7120, wait_flag = 0
child2 is killed
parent is killed.

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



结合书中的解释:

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

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


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

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

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



你可能感兴趣的:(linux编程)