操作系统实验二之信号处理实验

一、题目

1、编制一段程序,使用系统调用fork()创建两个子程序,再用系统调用signal()让父进程捕捉键盘上来的中断信号(即按Ctrl C键),当捕捉到中断信号后,父进程调用kill()向两个子进程发出信号,子进程捕捉到信号后,分别输出下面信息后终止: child process 1 is killed by parent! child process 2 is killed by parent! 父进程等待两个子进程终止后,输出以下信息后终止: parent process is killed!

2、在上述的程序中增加语句signal(SIGINT, SIG_IGN)和signal(SIGQUIT, SIG_IGN),观察执行结果并分析原因。这里signal(SIGINT, SIG_IGN)和signal(SIGQUIT, SIG_IGN)分别为忽略“Ctrl Z”键信号以及忽略“Ctrl C”中断信号。

二、实验过程及分析

要想做好这个实验,需要先学习一下关于linux下系统信号的基础知识。推荐下面两篇文章:
1. Linux 进程间通信 — 信号通信 — signal — signal(SIGINT, my_func); — 按键驱动异步通知
2. linux 捕获kill命令的信号

小实验一
1. 设计流程
操作系统实验二之信号处理实验_第1张图片
2. 代码

#include
#include
#include
#include

void waiting();
void stop();
void alarming();

int wait_mark;

void main(){
    int pid1, pid2;
    while((pid1 = fork()) == -1);//创建子进程1
    if(pid1 > 0 ){//如果是父进程
        while((pid2 = fork()) == -1);//创建子进程2
        if(pid2 > 0){//如果是父进程
            wait_mark = 1;//等待状态为1,等待中断信号
            signal(SIGINT,stop);//设置收到信号ctrl+C时,执行stop函数
            signal(SIGALRM,alarming);//设置收到SIGALRM(时钟)信号,则执行alarming函数
            waiting();//休眠5秒

            kill(pid1, 16);//向进程1发出信号16
            kill(pid2, 17);//向进程2发出信号17

            wait(0);//等待进程执行结束,同步
            wait(0);//等待进程执行结束,同步
            printf("parent precess is killed!\n");
            exit(0);//退出进程
        }
        else{
            wait_mark = 1;//等待中断信号
            signal(17,stop);//设置收到中断信号17,执行stop函数
            //signal(SIGINT,SIG_IGN);//设置收到ctrl+c时,忽略该信号
            while(wait_mark != 0);
            lockf(1,1,0);//加锁
            printf("child process2 is killed by parent!\n");
            lockf(1,0,0);//解锁
            exit(0);
        }
    }
    else{
        wait_mark = 1;
        signal(16,stop);设置收到中断信号16,执行stop函数
        //signal(SIGINT,SIG_IGN);设置收到ctrl+c时,忽略该信号
        while(wait_mark != 0);
        lockf(1,1,0);//加锁
        printf("child process1 is killed by parent!\n");
        lockf(1,0,0);//解锁
        exit(0);
    }
}

void waiting(){
    sleep(5);//休眠
    if(wait_mark != 0) kill(getpid(), SIGALRM);//向当前进程发出中断信号
}
void alarming(){
    wait_mark = 0;
}
void stop(){
    wait_mark = 0;
}

结果
这里写图片描述
  若按下ctrl+c,立即终止程序,并且只会输出“parent process is killed!”;若未按下ctrl+c,则过了5秒后,自动终止程序,输出如上图。

小实验二
代码

#include
#include
#include
#include

void waiting();
void stop();
int wait_mark;
void main(){
    int pid1, pid2;
    while((pid1 = fork()) == -1);
    if(pid1 > 0){
        while((pid2 = fork()) == -1);
        if(pid2 > 0){
            wait_mark = 1;//进入等待状态
            signal(SIGINT,stop); //接收到信号,执行stop
            waiting();//等待
            sleep(1);//休眠1秒
            kill(p1, 16);//向进程1发送信号16
            sleep(1);
            kill(p2, 17);//向进程2发送信号17
            wait(0);
            wait(0);
            printf("parent process is killed!\n");//输出 
            exit(0);//进程终止
        }
        else{
            signal(SIGINT,SIG_IGN); //忽略ctrl+c 
            signal(SIGQUIT,SIG_IGN);//忽略ctrl+z
            signal(17,stop); //接收父进程发送的信号 
            wait_mark=1;//等待中断
            waiting();//等该父进程发送终止信号信号 
            lockf(1,1,0); //加锁
            printf("child process 2 is killed by parent!\n"); 
            lockf(1,0,0);//解锁
            exit(0);   //进程终止 

        }
    }
    else{
        signal(SIGINT,SIG_IGN); //忽略ctrl+c 
        signal(SIGQUIT,SIG_IGN);//忽略ctrl+z
        signal(16,stop); //接收父进程发送的信号 
        wait_mark=1;//等待中断
        waiting();//等该父进程发送终止信号信号 
        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 sotp(){
    wait_mark = 0;
}

结果
这里写图片描述
  输出如上图。

分析
  两个实验程序的区别在于:
  第一个程序中,三个进程都可以收到SIGINT信号,所以如果按下ctrl+c,两个子进程会立即结束;而父进程中由于修改了SIGINT信号的默认响应方式,所以会正常运行结束。最终输出了“parent process is killed!”。
  第二个程序中,三个进程同样都可以接收到SIGINT信号,但是只有父进程响应了该信号,而子进程接收到该信号后,会忽它。因此,按下ctrl+c后,父进程向两个子进程发出kill信号,最终会输出图示结果并结束运行。

附:ctrl+c, ctrl+z信号说明
ctrl+c:发送 SIGINT 信号给前台进程组中的所有进程,常用于终止正在运行的程序。
ctrl+z:发送 SIGTSTP 信号给前台进程组中的所有进程,常用于挂起一个程序。

你可能感兴趣的:(操作系统实验)