Linux下的信号(一):信号的基本概念与产生
Linux下的信号(二):阻塞信号
一,什么是捕捉信号?
1,捕捉信号:信号处理方式三种方式中的一种,意思是既不忽略该信号,又不执行信号默认的动作,而是让信号执行自定义动作。捕捉信号要使用signal函数,为了做到这一点要通知内核在某种信号发生时,调用一个用户函数handler。在用户函数中,可执行用户希望对这种事件进行的处理。注意,不能捕捉SIGKILL和SIGSTOP信号。
2,系统捕捉信号的过程:
总结一下上图:
1>当一个正在运行的进程收到了中断,异常,或系统调用时,会从用户 态切换至内核态;
2>当内核处理完异常或中断时不会立即返回用户态,在回到用户态之前系统会检查要返回进程PCB中的signal位图信息。如果当前进程的pending表中有还未递达的信号(pending表中有标志是1),内核会将悬挂的信号进行处理:
3>如果悬挂信号的处理方式是执行自定义动作,那么此时会从内核态切换至用户态执行用户自定义的handler函数;
4>待系统处理完信号自定义的句柄函数时,系统会执行特殊的系统调用sigreturn再次回到内核态;
5>处理完sigreturn之后再次从内核态切换至用户态执行从主控流程main函数中上次被中断的地方继续向下运行……
3,捕捉信号过程的快速记忆(类似于数学公式中的∞):
0>一张图,两半,上为用户态(运行态),下面为内核态(管理态)。
1> 上图为信号的捕捉,处理流程。
2>图中黑色菱形是为了处理用户自定义的句柄。
3>图中有4个内核与用户的切换(1234)。
4>用户处理信号的时机:从内核态切回用户态时。
4,内核捕捉信号举例:
1>用户程序注册了SIGQUIT信号的处理函数sighandler。
2> 当前正在执行main函数,这时发生中断或异常切换到内核态。
3> 在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT递达。
4> 内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函数,sighandler和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是两个独立的控制流程。
5> sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态。
6> 如果没有新的信号要递达,这次再返回用户态就是恢复main函数的上下文继续执行了。
二,捕捉信号用到的函数
1)SIGALRM 信号:
时钟定时信号, 计算的是实际的时间或时钟时间, alarm函数使用该信号。
2)alarm函数:
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
alarm也称为闹钟函数。它可以在进程中设置一个定时器,当定时器指定的时间到时,它向进程发送SIGALRM信号。如果忽略或者不捕获此信号,则其默认动作是终止调用该alarm函数的进程。
返回值是0或者是以前设定的闹钟时间还余下 的秒数。如果seconds值为0,表示取消以前设定的闹钟,函数的返回值仍然是以前设定的闹钟时间还余下的秒数。
3)pause函数:
#include <unistd.h>
int pause(void);
pause函数使调用进程挂起直到有信号递达。pause只有出错的返回值。errno设置为EINTR表示“被信号中断”。
如果信号的处理动作是终止进程,则进程终止, pause函数没有机会返回;
如果信号的处理动作是忽略,则进程继续处于挂起状态, pause不返回;
如果信号的处理动作是捕捉,则调用了信号处理函数之后pause返回- 1;
4)sigaction函数:
#include <signal.h>
int sigaction(