一道关于信号的题
来源:互联网 发布:用网络看电视直播 编辑:程序博客网 时间:2024/04/30 10:34
信号是UNIX下常见的进程间通信机制。今天碰到一道信号方面题目,与大家分享,题目如下:
用fork创建两个子进程,调用signal()让父进程接收键盘上的中断信号(control-c),捕捉到信号后父进程用kill()向子进程发送自定义信号,子进程捕捉到信号后分别输出如下信息后终止:
父进程等待两个子进程结束后,输出如下信息后终止:
现给出如下程序:
可以看到,应用程序运行后,在按下键盘control-c后显示
Parent process is killed!就返回了shell。为什么没有显示应该显示的另外两句呢?
通过调试发现,父进程在接收到control-c,发送消息给子进程让子进程结束的时候,子进程就已经结束掉了,原因是子进程也接收到了control-c的按键并且默认结束了自己,也就是子进程并不是因为父进程发送信号通知自己结束而结束的,而是自己接收到的SIGINT使得自己结束的。那么要得到正确的输出就很简单,可以这么做:
在子进程中把一个空函数注册为处理信号SIGINT的函数,这样子进程接收了到control-c还可以继续运行。
在子进程创建好后:
重新编译运行程序,就可以得到正确结果了。
那么,假如不允许修改原来的程序,也要打印出正确结果怎么办呢?
方法也很简单,原来的程序之所以不能正确输出结果是因为两个子进程也接收到了control-c,因为这个按键是我们在shell里发送给程序的,解决的办法就是单独给父进程的发送SIGINT。
首先编译原来的程序:
运行生成的可执行文件:
然后打开一个新的shell,找出所有的a.out。
发现有三个a.out在运行,一般情况下数字小的就是父进程,也就是这里的3147,我们给这个进程单独发送SIGINT:
再切换回原来的shell,可以看到进程已经被终止了并且输出了正确结果:
用fork创建两个子进程,调用signal()让父进程接收键盘上的中断信号(control-c),捕捉到信号后父进程用kill()向子进程发送自定义信号,子进程捕捉到信号后分别输出如下信息后终止:
- Child process 1 is killed by parent!
- Child process 2 is killed by parent!
父进程等待两个子进程结束后,输出如下信息后终止:
- Parent process is killed!
现给出如下程序:
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/wait.h>
- #include <signal.h>
- #include <unistd.h>
- void waiting();
- void stop();
- static int wait_mark;
- int main(int argc, const char *argv[])
- {
- int p1, p2;
- int stdout;
- while ((p1 = fork()) == -1);
- if (p1 > 0)
- {
- while ((p2 = fork()) == -1);
- if (p2 > 0)
- {
- wait_mark = 1;
- signal(SIGINT, &stop);
- waiting();
- kill(p1, 16);
- wait(0);
- kill(p2, 17);
- wait(0);
- printf("Parent process is killed!\n");
- exit(0);
- }
- else
- {
- wait_mark = 1;
- signal(17, stop);
- waiting();
- lockf(stdout, 1, 0);
- printf("Child process 2 is killed by parent!\n");
- lockf(stdout, 0, 0);
- exit(0);
- }
- }
- else
- {
- wait_mark = 1;
- signal(16, stop);
- waiting();
- lockf(stdout, 1, 0);
- printf("Child process 1 is killed by parent!\n");
- lockf(stdout, 0, 0);
- exit(0);
- }
- return 0;
- }
- void waiting()
- {
- while (wait_mark != 0);
- }
- void stop()
- {
- wait_mark = 0;
- }
可以看到,应用程序运行后,在按下键盘control-c后显示
Parent process is killed!就返回了shell。为什么没有显示应该显示的另外两句呢?
通过调试发现,父进程在接收到control-c,发送消息给子进程让子进程结束的时候,子进程就已经结束掉了,原因是子进程也接收到了control-c的按键并且默认结束了自己,也就是子进程并不是因为父进程发送信号通知自己结束而结束的,而是自己接收到的SIGINT使得自己结束的。那么要得到正确的输出就很简单,可以这么做:
在子进程中把一个空函数注册为处理信号SIGINT的函数,这样子进程接收了到control-c还可以继续运行。
- /* 定义一个空函数 */
- void blank()
- {
- /* do nothing */
- }
在子进程创建好后:
- signal(SIGINT, blank);
重新编译运行程序,就可以得到正确结果了。
- $ gcc a.c
- $ ./a.out
- ^CChild process 1 is killed by parent!
- Child process 2 is killed by parent!
- Parent process is killed!
那么,假如不允许修改原来的程序,也要打印出正确结果怎么办呢?
方法也很简单,原来的程序之所以不能正确输出结果是因为两个子进程也接收到了control-c,因为这个按键是我们在shell里发送给程序的,解决的办法就是单独给父进程的发送SIGINT。
首先编译原来的程序:
- $ gcc b.c
运行生成的可执行文件:
- $ ./a.out
然后打开一个新的shell,找出所有的a.out。
- $ ps -e | grep 'a.out'
- 3147 pts/0 00:00:01 a.out
- 3148 pts/0 00:00:01 a.out
- 3149 pts/0 00:00:01 a.out
发现有三个a.out在运行,一般情况下数字小的就是父进程,也就是这里的3147,我们给这个进程单独发送SIGINT:
- $ kill -s INT 3147
再切换回原来的shell,可以看到进程已经被终止了并且输出了正确结果:
- Child process 1 is killed by parent!
- Child process 2 is killed by parent!
- Parent process is killed!
0 0
- 一道关于信号的题
- 一道关于信号的题
- 关于数据库的一道题??
- 关于继承的一道题
- 关于 static 的一道题
- 关于一道题的思考
- 关于C++的一道题
- 关于jvm的一道题
- 关于蓝桥杯的一道题
- 关于textarea的一道题
- 一道简单的关于图的题
- 关于一道招聘题的分析
- 关于位运算的一道笔试题
- 一道关于字符串逆序的笔试题
- 另外一道关于Random的编程题
- 一道关于目录的编程题
- 关于printf类型提升的一道题
- Google关于递归的一道笔记题
- iOS8新特性扩展(Extension)应用之二——分享插件
- HDU 2660 Accepted Necklace(DFS解01背包)
- Ext.data.HttpProxy传参的中文乱码解决办法
- 【深入浅出Node.js系列十二】Nodejs日志管理log4js
- android 游戏 实战打飞机游戏 菜单页面(1)
- 一道关于信号的题
- httpModules 与 httpHandlers
- 深入理解计算机系统--->并发与并行
- Retrofit初体验,复杂数据gson解析
- 【深入浅出Node.js系列十三】用Nodejs连接MySQL
- Eclipse调试Java的10个技巧
- android led 驱动
- MyBatis两种操作数据库的结构
- 【深入浅出Node.js系列十四】Nodejs异步流程控制Async