信号在Linux中是一个比较常见的概念,例如我们按Ctrl+C中断前台进程,通过Kill命令结束进程都是通过信号实现的。下面就以Ctrl+C为例简单的说明信号的处理流程:
用kill -l命令可以察看系统定义的信号列表:
$ kill –l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT
17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU
25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN
35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4
...
每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,可以通过man signal(7)查看详细说明:
Signal Value Action Comment
-------------------------------------------------------------------------
SIGHUP 1 Term Hangup detected on controlling terminal
or death of controlling process
SIGINT 2 Term Interrupt from keyboard
SIGQUIT 3 Core Quit from keyboard
SIGILL 4 Core Illegal Instruction
...
产生信号的条件主要有:
如果不想按默认动作处理信号,用户程序可以调用sigaction函数接管该信号的处理流程。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下:
sigaction函数可以读取和修改与指定信号相关联的处理动作,它的声明如下:
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
其中关键就是第二个参数act,他是一个sigaction类型,结构如下:
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
其中关键的是sa_handler这个参数,它通常可以有如下几种赋值:
另外,如果在调用信号处理函数时,除了当前信号被自动屏蔽之外,还希望自动屏蔽另外一些信号,则用sa_mask字段说明这些需要额外屏蔽的信号,当信号处理函数返回时自动恢复原来的信号屏蔽字。
下面就以一个简单的例子演示下如何实现捕捉信号的过程,该函数的功能比较简单,就是在Ctrl+C的时候并不直接退出,而是先输出一条华丽的分割线后才退出。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
void show_and_exit(int sig)
{
printf("\n----------------------------\n");
exit(0);
}
int main(void)
{
struct sigaction act = {0}, oldact = {0};
act.sa_handler = show_and_exit;
//act.sa_flags = SA_RESETHAND | SA_NODEFER;
//sigaddset(&act.sa_mask, SIGQUIT);
sigaction(SIGINT, &act, &oldact);
int count = 0;
while(1)
{
sleep(1);
printf("sleeping %d\n", count++);
}
}
执行该函数结果如下:
tianfang > run
sleeping 0
sleeping 1
sleeping 2
^C
----------------------------
tianfang >