linux信号
信号是由用户、系统、进程发给目标进程的信息,以通知目标进程某个状态的改变或者系统异常。linux信号产生条件为:
- 在终端输入字符,比如ctrl+z
- 系统异常
- 系统状态变化。比如 alarm 定时器到期产生SIGALRM信号
- 运行kill或者调用kill函数
查看Linux支持的信号命令: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 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
给一个进程发送信号
使用 kill 函数:(man 2 kill)
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
举个栗子:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
int main()
{
pid_t pid = fork();
if (pid > 0)
{
printf("in parent program..., child id: %d\n", pid);
while (1){}
}
else if (pid == 0)
{
sleep(2);
printf("in child program..., cur id: %d\n", getpid());
pid_t ppid = getppid();
printf("befor kill, ppid is %d\n", ppid);
int ret = kill(ppid, SIGINT);
printf("kill result is: %d, errno: %d\n", ret, errno);
sleep(2);
ppid = getppid();
printf("after kill, ppid is %d\n", ppid);
}
return 0;
}
运行结果为:
in parent program..., child id: 11519
in child program..., cur id: 11519
befor kill, ppid is 11518
kill result is: 0, errno: 0
sunny@hst:~/program/cpp$ after kill, ppid is 1
在子进程,发送SIGINT(终端终端)信号给父进程,父进程退出。子进程被init进程接管,子进程的父进程号变为1
信号处理
使用signal函数捕获信号
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
定义sighandler_t类型的函数,该函数接受一个int类型的参数,这个参数指的是信号类型。信号函数应该是可重入的,严禁调用一些不安全的函数。
SIGKILL和SIGSTOP信号不能被捕获或者忽略。
除了用户自定义的信号处理函数外,x86_64-linux-gnu/bits/signum-generic.h 文件中,定义了三个其他处理方式:
#define SIG_ERR ((__sighandler_t) -1) /* Error return. */
#define SIG_DFL ((__sighandler_t) 0) /* Default action. */
#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */
SIG_IGN 表示忽略信号,SIG_DFL表示使用信号的默认处理方式。