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命令的信号
#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 信号给前台进程组中的所有进程,常用于挂起一个程序。