今天一直在研究嵌入式的实验作业,有一组代码一直没想明白,百度搜到了许多和我相同实验的同学,但是没有一个解除了我的疑惑。在对代码中每个函数进行了仔细的研究后,终于把代码来龙去脉弄懂了。

SIGINT指令=Ctrl+c

最主要坑的还是fork()创建的子进程会完完全全克隆他的父进程,包括父进程当前的代码段,也就是fork()之后,父进程执行到哪一步了,子进程就从哪一步开始执行。

子进程也会复制   父进程之前的  监听函数,例如下面代码中的

signal(SIGINT,stop);

子进程也会复制这个函数,所以当你按下ctrl+c时,父进程和子进程都会调用stop函数。

以下是代码以及注释:

#include<stdio.h>
#include<signal.h>
#include<unistd.h> 
int wait_mark;
void waiting(), stop();
int main(int argc, char *argv[]) {
    int p1, p2;
    signal(SIGINT,stop); //监听ctrl+c,如果按下了,则执行stop函数
    while((p1 = fork()) == -1);//这里创建了一个子进程,子进程和父进程一样也开始监听ctrl+c
    if (p1 > 0)	/*在父进程中*/
    { ①	
        while((p2 = fork()) == -1);	//再创建一个子进程,同样也监听ctrl+c
        if (  p2 > 0)	/*在父进程中*/
        {     ②	
            wait_mark = 1;
            waiting();//只要wait_mark等于1,就会一直等待。而执行stop函数后,wait_mark=0了就跳出了循环。
            kill(p1, 10);//在这段代码中这个方法相当于没啥用,这个函数给p1发送了10的指令,让p1进程再执行一次stop方法。
            kill(p2, 12);//原理同上
            wait(NULL);//等待子程序结束
            wait(NULL);//同上
            printf("parent process exit!\n");
            exit(0);
        }
        else	/*在子进程 2 中*/
        {
            wait_mark = 1;
            signal(12, stop);
            waiting();//只要wait_mark等于1,就会一直等待。而执行stop函数后,wait_mark=0了就跳出了循环。

            lockf(1, 1, 0);
            printf("child process 2 is killed by parent!\n");
            lockf(1, 0, 0);
            exit(0);
        }
    }
    else	/*在子进程 1 中*/
    {
        wait_mark = 1;
        signal(10, stop);
        waiting();//只要wait_mark等于1,就会一直等待。而执行stop函数后,wait_mark=0了就跳出了循环。

        lockf(1, 1, 0);
        printf("child process 1 is killed by parent!\n");
        lockf(1, 0, 0);
        exit(0);
    }
}

void waiting()
{
    while(wait_mark != 0);
}
void stop()
{
    wait_mark = 0;
}


最开始父进程,p1进程,p2都在wait()中等待,当按下ctrl+c时,父进程,p1进程,p2进程三个进程都监听到了ctrl+c,都会执行stop函数,从而把3个进程内的wait_mark置为0,跳出循环。所以才会顺序执行输出这3句话。

所以

    kill(p1, 10);//在这段代码中这个方法相当于没啥用,这个函数给p1发送了10的指令,让p1进程再执行一次stop方法。
    kill(p2, 12);//同上

这两个函数没起到作用,可以直接注释掉,无伤大雅。


之后老师又给出了一个问题

⑴     如果把signal(SIGINT,stop)放在①号和②号位置,结果会怎样并分析原因。


signal(SIGINT,stop)放在①号位置时,子进程p1就监听不到signal(SIGINT,stop)了,而ctrl+c本身就有一个中断进程的作用,这时候如果按下了ctrl+c,p1直接被中断,不再等待了,也不执行子进程之后的代码了。

执行结果:


signal(SIGINT,stop)放在②号位置时,子进程p1、p2就监听不到signal(SIGINT,stop)了,而ctrl+c本身就有一个中断进程的作用,这时候如果按下了ctrl+c,p1、p2直接被中断,不再等待了,也不执行之后的代码了。

执行结果:


所以

    kill(p1, 10);//在这段代码中这个方法相当于没啥用,这个函数给p1发送了10的指令,让p1进程再执行一次stop方法。
    kill(p2, 12);//同上

这两个函数实际上又没起到作用。

就是这个坑,排了挺久的,主要还是自己对函数的原理不太熟悉。

Logo

更多推荐