信号的产生:
信号的产生可以分为四种方式,不论是哪种方式都是操作系统发送的信号
1.通过终端按键产生(键盘中的Ctrl+c Ctrl +v Ctrl +\操作前台进程 )
按键后进程立即终止,并core dump(核心转储)。
核心转储就是进程在异常终止之前操作系统将进程当前进程在内存中的有效数据转储到硬盘中,并在进程的当前目录产生一个core+进程pid的文件以便于事后调试。如果没有产生相应的core文件可以使用ulimit -a查看core文件的大小如果为0可以使用ulimit -c +大小进行调整
2.系统函数产生
kill 函数可以向指定进程发送指定信号(kill命令也是调用kill函数实现的)
int kill(pid_t pid, int sig);
信号的编号使用kill -l 查看,其中1-31号信号时普通信号34-64号信号为实时信号
raise函数是将信号发送给自己
int raise(int sig);
abort函数使当前进程收到异常信号而中止
void abort(void);
就像exit函数⼀样,abort函数总是会成功的,所以没有返回值。
3.软件产生
使用管道时读端文件描述符被关闭,依然写时就会触发SIGPIPE信号
alarm函数unsigned int alarm(unsigned int seconds)seconds秒之后就将SIGALARM信号发送给当前进程,默认是将当前进程终止
4.硬件异常
除0
解引用空指针内存错误页表无法映射触发异常操作系统解释成11号信号SIGSEGV发送给目标进程,进程终止。
二、信号的处理
1.忽略此信号
2.执行默认处理函数
3.信号的捕捉:提供一个处理函数,操作系统遇到这个信号时会从内核态切换到用户态执行这个函数(9号信号不能被捕捉)
三、信号在内核中
信号从信号产生到信号被处理之前叫做信号未决(pending),信号正在被处理的过程叫做信号的递达(delivery)在内核中使用位图的数据结构保存1-31号普通信号。
信号在递达之前可能会被阻塞(block),被阻塞的信号将保持在未决的状态直到进程解除阻塞信号才能被递达(注意与忽略信号的区别,信号的忽略是在递达之后进行的操作)
bolck位图中的每一个比特位位的位置都表示的是信号编号,位图中比特位的内容中0表示未被阻塞1表示被阻塞
pending位图中每一个比特位表示的是信号的编号,比特位的内容表示该信号是否被递达0表示未被递达,1表示被递达(信号产生了)。
handler表是一个函数指针数组,数组内部存储的是递达之后处理的函数地址。
但block和pending二者之间没有必然关系
图中SIGUP信号未被阻塞也未产生过,如果被递达操作是默认处理动作;SIGINT信号产生过了被阻塞,所以在解除阻塞前不能被递达,没有被解除阻塞前不能忽略,因为有可能会被解除阻塞。SIGQUIT信号没有产生过,一旦产生就会被阻塞,递达后的处理动作是用户自定义的handler.