信号的基本概念
SIGABRT 当进程调用abort函数时,系统向该进程发送该信号,默认情况下,该信号会杀死进程,并产生核心转储文件
SIGALRM 调用alarm()或者settimer()设置的实时定时器一旦到期,内核将产生该信号
SIGBUS 产生该信号,说明某种内存访问错误
SIGCHLD 当父进程的某一子进程终止时,内核向父进程发送该信号,当父进程的某一子进程因收到信号而停止或恢复时也可能向父进程发送该信号
SIGCLD 跟SIGCHLD信号同义
SIGCONT 将该信号发送给已停止的进程,进程将恢复运行
SIGFPE 该信号因特定类型的算术错误而产生,比如除以0
SIGHUP 当终端断开时,将发送该信号给终端控制进程,还可用于守护进程,许多守护进程收到该信号后重新进行初始化并读取配置文件
SIGILL 如果进程试图执行非法,格式不正确的机器语言指令,系统就会向该进程发送该信号
SIGINFO
SIGINT 当用户键入终端中断字符(如ctrl+c),终端驱动程序就发送该信号给前台进程组,该信号的默认行为是终止进程
SIGIO 利用fcntl()系统调用的打开文件爱你描述符发生io事件时产生该信号
SIGIOT 与SIGABRT信号同义
SIGKILL 必杀信号,处理器程序无法将其阻塞忽略或者捕获,总能杀死进程
SIGPIPE 当进程试图向管道,FIFO或者套接字写入信息时,如果这些设备并无相应的阅读进程,系统将产生该信号
SIGPOLL 与SIGIO信号同义
SIGPROF 有setitimer()调用所设置的性能分析定时器一过期,内核就产生该信号
SIGPWR 电源故障信号
SIGQUIT
SIGSEGV 当程序对内存的引用无效时,就会产生该信号
SIGSTOP 必停信号,处理器程序无法将其阻塞忽略或者捕获
SIGSYS 如果进程发起的系统调用有误,那么将产生该信号
SIGTERM 终止进程的标准信号
SIGTRAP 该信号用来实现断点调试以及strace
SIGTSTP 作业控制的停止信号,通常是ctrl+z
改变信号处置
#include<signal.h>
void (*signal(int sig,void(*handler)(int)))(int);
可以改写为singhandler_t signal(int sig,sighandler_t handler);
int kill(pid_t pid,int sig);//如果pid大于0,那么发送信号该pid指定的进程,等于0,发送给与调用进程同组的每个进程,包括调用进程本身,小于-1会向组id的呢关于该pid绝对值的进程组内的所有下属进程发送信号,等于-1,调用进程有权将信号发往每个目标进程,出去init和调用进程本身
int raise(int sig);//向自身发送信号
int killpg(pid_t pgrp,int sig);//向某一进程组的所有成员发送信号
char *strsignal(int sig);//显示信号描述
int sigemptyset(sigset_t *set);//初始化一个为包含任何成员的信号集
int sigfillset(sigset_t *set);//初始化一个信号集,使其包含所有信号
int sigaddset(sigset_t *set,int sig);//增加单个信号
int sigdelset(sigset_t *set,int sig);//删除单个信号
int sigismember(const sigset_t *set,int sig);//测试信号sig是否是信号集set的成员
int sigandset(sigset_t *set,sigset_t *left,sigset_t *right);//取left集和right集的交集,放到set集中
int sigorset(sigset_t *dest,sigset_t *left,sigset_t *right);//succeed return 0,else -1
int sigisemptyset(const sigset_t *set);//if empty return 1
int sigprocmask(int how,const sigset_t *set,sigset_t *oldset);//获取或者修改进程的信号掩码
SIG_BLOCK 将set指向信号集内的指定信号添加到信号掩码中,即将信号掩码设置为当前值和set的并集
SIG_UNBLOCK 将set指向信号集中的信号从信号掩码中移除
SIG_SETMASK 将set指向的信号集赋给信号掩码
只想获取信号掩码,只需要吧set参数设为空
//处于等待状态的信号
int sigpending(sigset_t *set); //如果进程接受了一个该进程正在阻塞的信号,那么会将该信号增加到进程的的等待信号集中,当解除对该信号的锁定时,会随之将信号传递给此进程
//改变信号处置
int sigaction(int sig,const struct sigaction *act,struct sigaction *oldact);
struct sigaction{
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
}
#include<unistd.h>
//等待信号
int pause(void);//暂停进程的执行,直至信号处理器函数中断该调用为止
//执行非本地跳转时的信号掩码进行显示控制
#include<setjmp.h>
int sigsetjmp(sigjmp_buf env,int savesigs);//如果savesigs非0,那么将调用sigsetjmp()是进程的当前信号掩码保存与env中,之后通过指定相同env参数的siglongjmp()调用进行恢复。如果为0,则不会保存和恢复进程的信号掩码
void siglongjmp(sigjmp_buf env,int val);
//异常终止进程
#include<stdlib.h>
void abort(void);//通过产生SIGABRT信号来终止调用进程
//备选栈中处理信号
#include<signal.h>
int sigalstack(const stack_t *sigstack,stack_t *old_sigstack);//sigstack所指向的数据结构描述了新备选信号栈的位置和属性。old_sigstack指向的结构则用于返回上一备选信号栈的相关信息,两个参数均可为NULL
typedef struct {
void *ss_sp; //备选栈开始地址
int ss_flags; //标志,SS_ONSTACK进程正在备选信号栈上执行再试图调用sigalstack()创建新备选信号栈会产生错误,SS_DISABLE警用当前已创建的备选信号栈
size_t ss_size; //备选栈的大小
}stack_t;
如果在使用sigaction()创建处理器函数时设置了SA_SIGINFO标志,那么在收到信号时处理器函数可以获取该信号的一些附加信息,只需要将处理器函数声明如下
void handler(int sig,siginfo_t *siginfo,void *ucontext);//sig表示信号编号,siginfo用于提供信号的附加信息的一个结构,该结构会与最后一个参数ucontext一起
为信号修改SA_RESTART标志
int siginterrupt(int sig,int flag);//flag为1,针对信号sig的处理器函数将会中断阻塞的系统调用的执行,如果flags为假,那么在执行了sig的处理器函数之后,会自动启动阻塞的系统调用