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

来源:互联网 发布:中国城镇住户调查数据 编辑:程序博客网 时间:2024/06/06 03:42

一、题目

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. 设计流程
这里写图片描述
2. 代码

#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<unistd.h>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<stdio.h>#include<stdlib.h>#include<signal.h>#include<unistd.h>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 信号给前台进程组中的所有进程,常用于挂起一个程序。

1 0
原创粉丝点击