Linux-信号
1、定义
信号
引用APUE第二版中所述,信号就是软件中断,提供了一种处理异步事件的方法。沿用《Linux高性能服务器编程》中对于信号的定义,信号是由用户、系统或进程发送给目标进程的信息。例如用户在Shell中执行程序A(非后台进程),可以通过Ctrl+C的方式给程序A发送一个SIGINT中断信号,默认情况下程序A为被终止掉。
在Linux系统中中,总共有31个标准信号,全部被定义在头文件<bits/signum.h>中,常用的主要有如下几种:
| 信号 | 含义 | 默认 |
| SIGHUP | 控制终端挂起 | 终止 |
| SIGINT | 系统中断 | 终止 |
| SIGABRT | 系统异常终止 | 终止 |
| SIGCLD | 子进程状态改变 | 忽略 |
| SIGCHLD | 与SIGCLD相同 |
信号集是一组信号的集合,linux中使用sigset_t来表示。
2、函数
①、信号函数
int kill (__pid_t __pid, int __sig) 发送信号
给指定的进程发送sig信号,如果pid=0则发送给本进程组中的其他进程。 如果pid=-1发送给除去init进程之外的所有进程,pid<-1信号发送给组ID为-pid进程组中所有成员。
int sigaction (int __sig, const struct sigaction *__restrict __act, struct sigaction *__restrict __oact) 处理信号
指定__act 函数为信号sig的默认处理函数。同时返回旧的信号处理函数。
信号处理函数有SIG_DFL(使用信号默认处理) SIG_IGN(忽略信号)
②、信号集处理函数(POSIX标准)
int sigemptyset (sigset_t *__set) 信号集置空
int sigfillset (sigset_t *__set) 设置所有信号
int sigaddset (sigset_t *__set, int __signo) 增加信号
int sigdelset (sigset_t *__set, int __signo) 删除信号
int sigismember (const sigset_t *__set, int __signo) 判断是否信号是否属于信号集
int sigprocmask (int __how, const sigset_t *__restrict __set, sigset_t *__restrict __oset) 设置进程信号集掩码,被屏蔽的信号将不会被进程接受。
int sigpending (sigset_t *__set) 取消信号挂起
3、例子
① 让程序忽略某个信号
struct sigaction sa; sa.sa_handler = SIG_IGN; // 忽略信号 sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGHUP, &sa, NULL);
② 守护程序启动异常终止的子程序
main.c
int main(int argc, char *argv[]) {
set_Daemon();
start_main();
return 1;
}
int start_main(){
// add your code
}
int set_Daemon(){
// clear file create mask
umask(0);
struct rlimit rl;
pid_t pid;
// get the open file describle number limit
if(getrlimit(RLIMIT_NOFILE, &rl)<0){
printf("get the limits err\n");
return -1;
}
// create a new session. create a child process, and the parent process quit
if( (pid = fork()) <0) {
printf("fork error\n");
return -1;
}
else if(pid!=0){
printf("fork ok, parent out\n");
exit(0);
}
printf("fork ok, child continue\n");
setsid();
// signal handle, igore the sighup signal
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGHUP, &sa, NULL);
if( (pid = fork()) <0) {
printf("fork error\n");
return -1;
}
else if(pid!=0){
exit(0);
}
chdir("/");
// close all the file descriptors
if(rl.rlim_max>1024){
rl.rlim_max = 1024;
}
for(int i=0; i<rl.rlim_max; i++){
close(i);
}
// attach 0,1,2 file descriptor to /dev/null
int fd0, fd1, fd2;
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
}
int set_signal(){
signal(SIGABRT, restart);
signal(SIGINT, restart);
signal(SIGCLD, restart);
signal(SIGCHLD, restart);
}
void restart(int sig){
if(sig==SIGABRT){
printf("get the SIGABRT signal\n");
}
else if(sig==SIGCLD || sig==SIGCHLD){
printf("get the SIGCLD|SIGCHLD signal\n");
}
else if(sig==SIGINT){
printf("get the SIGINT signal\n");
exit(-1);
}
}

浙公网安备 33010602011771号