信号的产生以及处理方式
Posted ZDF0414
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了信号的产生以及处理方式相关的知识,希望对你有一定的参考价值。
/*************************************************************************************************************/
为了理解信号,先从我们最熟悉的场景说起:
1.用户输入命令,在Shell下启动一个前台进程。
2.用户按下Ctrl-C,这个键盘输入产生一个硬件中断。
3.如果CPU当前正在执行这个进程的代码,则该进程的用户空间代码暂停执行,CPU从用户态
切换到内核态处理硬件中断。
4.终端驱动程序将Ctrl-C解释成一个SIGINT(#2)信号,记在该进程的PCB中(也可以说发送了一
个SIGINT信号给该进程)。
5.当某个时刻要从内核返回到该进程的用户空间代码继续执行之前,首先处理PCB中记录的信号,发现有一个SIGINT信号待处理,而这个信号的默认处理动作是终止进程,所以直接终止进程而不再返回它的用户空间代码执行。
前台进程:影响命令行工作的进程
一个命令 后面加个&可以放到后台运行,这样Shell不必等待进程结束就可以接受新的命令,启动新的进程。Shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接到像Ctrl-C这种控
制键产生的信号。
信号相对于进程的控制流 程来说是异步的,也就是说该进 程的用户空间代码执行到任何地方都有可能收到信号而终止。
/*************************************************************************************************************/
一、信号的产生方式:
(1)通过终端按键产生信号(即组合键),但只能发给前台进程;
(2)硬件异常产生信号,调用系统函数向进程发信号,这些条件由硬件检测到并通知内核,然后内核向当前进程发送适当的
信号。
(硬件异常比如:当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释
为SIGFPE信号发
送给进程; 再比如:当前进程访问了非法内存地址,,MMU会产生异常,内核
将这个异常解释为
SIGSEGV信号发送给
进程)
(3)由软件条件产生信号. 如
kill命令,kill 函数,raise 函数(自己给自己发送信号)
int kill(pid_t pid,int sig);
返回值:成功-->ret==0;失败返回-1,error 被设置。(附:mykill
的实现见最后...六...)
int raise(int sig); //自己给自己发信号
返回值:成功-->ret==0, 失败返回非零。
/*************************************************************************************************************/
二、信号的处理方式:
(1)忽略此信号;
(2)执行该信号的默认处理动作;
(3)自定义该信号的处理动作(信号捕捉);
/*************************************************************************************************************/
三、SIGQUIT与Core Dump
SIGQUIT的默认处理动作是终止进程并且Core
Dump,它的组合键为:Ctrl+\
Core Dump:当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部
保存到磁盘上,文件名通常是core.
core文件的作用:进程异常终止通常是因为有Bug,比如非法内存访问导致段错误,事后可以用调试器检查core文件以
查清错误原因,这叫做Post-mortem
Debug.
默认是不允许产生core文件的(它的size=0),因为core文件中可能包含用户密码等敏感信息,不安全。
在开发调试阶段可以用ulimit命令改变这个限制,允许产生core文件。指令:#ulimit
-c size
(1)改变 core 文件的大小
(2)下面的代码在运行时会触发段错误,并生成 core 文件。利用该文件进行调试就会定位到错误。
#./a.out 运行 a.out 程序(在运行时会触发段错误,并生成 core 文件:core.id)(id为进程号)
/*************************************************************************************************************/
四、abort函数使当前进程接收到SIGABRT信号而异常终止。
#include <stdlib.h>
void abort(void);
就像exit函数一样,abort函数总是会成功的,所以没有返回值。
/*************************************************************************************************************/
五、alarm函数 和SIGALRM信号。
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号,该信号的默认处理动作是终止当前进程。
这个函数的返回值是0或者是以前(它的前一次)设定的闹钟时间还余下
的秒数
下面程序的功能:
(1)先设置闹钟时间为3s;
(2)再sleep(1)后,重新设置闹钟时间为 1s,则alarm函数的返回值为2s;
(3)count一直增加,1s后,闹钟时间到,向进程发送终止信号,进程终止。
/*************************************************************************************************************/
六、自己实现 kill 函数 mykill
把a.out 程序运行起来后,在另一个终端上用 #./mykill pid signum 终止该程序
函数main.c的代码:
函数 mykill的实现:
/*************************************************************************************************************/
以上是关于信号的产生以及处理方式的主要内容,如果未能解决你的问题,请参考以下文章