一、什么是信号
信号是一种中断,即中止(注意不是终止)当前正在执行的任务,转而执行其它任务(可能返回也可能不返回),中断分为硬件中断(硬件设备产生的中断)和软件中断(其它程序产生的中断)。
软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注
意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。
二、信号的处理
1、忽略。
2、终止进程。
3、终止进程并产生core文件。
4、捕获信号并处理。
三、常见的信号
SIGINT(2) Ctrl+c 产生的信号
SIGQUIT(3) Ctrl+* 产生的信号
SIGABRT(6) 调用abort*函数,产生此信号
SIGFPE(8) 浮点数例外,除以0、浮点溢出等
SIGKILL(9) 不能被捕获或忽略,常用于杀死进程
SIGSEGV(11) 段错误信号,非法访问内存产生的信号
SIGTSTP(20) Ctrl+z 生产的信号
SIGCHLD(17) 子进程状态改变信号
注意:在终端中执行 kill -l 可以显示出所有信号
以下是比较常见的全部信号
四、信号的捕获
sighandler_t signal(int signum, sighandler_t handler);
功能:信号处理注册函数。
signum:信号的编号(1~31),也可以是宏。
sighandler_t handler:是函数指针,模型:typedef void (*sighandler_t)(int);
注意:在某些UNIX系统上,signal注册的函数只执行一次,执行完后就恢复成默认处理方式,如果长期使用该函数处理信号,可以在函数结束前再注册一次。
五、发送信号
int kill(pid_t pid, int sig);
功能:向指定的进程发送信号。
pid > 0 :向进程号为pid的进程发送信号。
pid = 0 : 向进程组发送信号。
pid = -1 :向所有(有权利发送信号的)进程发送信号。
pid < -1 : 向进程号为绝对值pid的进程号发送信号。
sig:信号的编号。sig为0时,kill不会发送信号,但是会进行错误检查(检查进程号或者进程组id是否存在)。
int raise(int sig);
功能:向当前进程发送信号。
**sig:**信号的编号。
六、休眠
int pause(void);
功能:一旦执行,进程就会进行无尽的休眠(暂停),知道遇到信号。先执行信号处理函数才会从休眠中醒来。
unsigned int sleep(unsigned int seconds);
功能:休眠指定秒数,当有信号来临时会提前醒来,提前醒来会返回剩余的秒数。
**seconds:**休眠的秒数。
七、闹钟
unsigned int alarm(unsigned int seconds);
功能:告诉内核seconds秒后发送SIGALRM信号
seconds:秒数。
返回值:如果之前设定的时间还没有到,则会重新设置(覆盖),并返回之前设置的剩余秒数。
八、信号集与信号屏蔽
信号集:信号的集合,由128位二进制组成,每一位代表一个信号。
注意:当信号集里面的位数为1时表示的是要屏蔽这个信号。
信号屏蔽:当做一些特殊操作时,我们会希望有些信号来而有些信号不要来,而与设置信号忽略不同的,信号屏蔽只是暂时不来,并且可以获取这段时间发生哪些信号。
注意:每个进程都有一个信号掩码(信号集)。
int sigemptyset(sigset_t* set);
功能:清空信号集,把所有位设置为0。
*sigset_t set:**定义的信号集
int sigfillset(sigset_t* set);
功能:把信号集所有的位置为1。
int sigaddset(sigset_t* set,int signum);
功能:往信号集里面添加一个信号。
int signum:信号。
int sigdelset(sigset_t* set,int signum);
功能:删除信号集里面的一个信号。
int sigismember(const sigset_t *set, int signum);
功能:判断信号里面有没有signum信号。
int sigprocmask(int how, const sigset_t *set,sigset_t *oldset);
功能:检查,修改进程的信号掩码
how:
SIG_BLOCK 设置当前信号掩码与set的并集为新的信号掩码,添加。
SIG_UNBLOCK 新的信号掩码是当前掩码与set补集的交集,删除。
SIG_SETMASK 把set当作新的信号掩码,重新设置。
set:可以为空,则获取信号掩码。
oldset:旧的信号屏幕掩码。
int sigpending(sigset_t *set);
功能:获取信号屏蔽期间发生的信号,当信号屏蔽解除后就没了。
注意:在信号屏蔽期间发生的信号,无论多少次(不可靠信号),只能捕获一次。