Linux系统中,信号是内核向进程发送的异步通知,用于告知进程发生了某种事件,比如如用户按下中断键、非法内存访问、定时器到期等。信号可以由系统发送,也可以由其他进程或应用程序自身发送。Linux支持多种信号,每种信号都有一个唯一的整数编号和一个默认的动作。
Linux信号集(sigset_t
)是一个数据结构,用于表示信号集,即一组信号。sigset_t
类型通常用于以下几种场景:
-
阻塞信号:使用
sigprocmask()
函数,进程可以创建一个信号掩码,用于暂时阻止某些信号的交付。 -
等待信号:使用
sigwait()
、sigwaitinfo()
或sigtimedwait()
函数,进程可以等待信号集中的任一信号的到来。 -
捕获信号:使用
signal()
或sigaction()
函数,进程可以指定对特定信号的处理方式,例如忽略信号、执行自定义的信号处理函数或执行默认动作。 -
发送信号:使用
kill()
、raise()
或pthread_kill()
函数,可以向进程或线程发送信号。
下面是一些常用的Linux信号及其编号和默认动作:
- SIGHUP (1):挂起信号,通常在终端挂起时发送。默认动作是终止进程。
- SIGINT (2):中断信号,通常由用户按下Ctrl+C触发。默认动作是终止进程。
- SIGQUIT (3):退出信号,通常由用户按下Ctrl+\触发。默认动作是终止进程并产生核心转储(core dump)。
- SIGILL (4):非法指令信号,当进程执行非法指令时发送。默认动作是终止进程并产生核心转储。
- SIGABRT (6):通常与abort()函数关联,用于报告程序错误。默认动作是终止进程并产生核心转储。
- SIGFPE (8):浮点异常信号,如除以零。默认动作是终止进程。
- SIGKILL (9):终止信号,不能被捕捉或忽略。默认动作是立即终止进程。
- SIGSEGV (11):段错误信号,通常由无效内存引用触发。默认动作是终止进程并产生核心转储。
- SIGPIPE (13):管道破裂信号,当进程尝试向已关闭的管道写入时发送。默认动作是终止进程。
- SIGTERM (15):终止信号,通常用于请求进程正常终止。默认动作是终止进程。
- SIGCHLD (17):子进程状态变更信号,当子进程终止或停止时发送给父进程。默认动作是忽略。
- SIGCONT (18):继续信号,用于继续一个已停止的进程。默认动作是继续进程。
- SIGSTOP (19):停止信号,用于停止进程。不能被捕捉或忽略。默认动作是停止进程。
- SIGTSTP (20):终端停止信号,通常由用户按下Ctrl+Z触发。默认动作是停止进程。
- SIGTTIN (21):后台进程试图从控制终端读取时发送。默认动作是停止进程。
- SIGTTOU (22):后台进程试图写入控制终端时发送。默认动作是停止进程。
这些信号可以通过signal
或sigaction
函数来处理,也可以在程序中通过sigset_t
类型的信号集来操作。信号集通常通过sigemptyset()
、sigfillset()
、sigaddsig()
、sigdelset()
和sigsuspend()
等函数来初始化、填充、添加、删除信号或等待信号集中的信号。
/**
int sigemptyset(sigset_t *set);
- 功能:清空信号集中的数据,将信号集中的所有的标志位置为0
- 参数:set,传出参数,需要操作的信号集
- 返回值:成功返回0, 失败返回-1
int sigfillset(sigset_t *set);
- 功能:将信号集中的所有的标志位置为1
- 参数:set,传出参数,需要操作的信号集
- 返回值:成功返回0, 失败返回-1
int sigaddset(sigset_t *set, int signum);
- 功能:设置信号集中的某一个信号对应的标志位为1,表示阻塞这个信号
- 参数:
- set:传出参数,需要操作的信号集
- signum:需要设置阻塞的那个信号
- 返回值:成功返回0, 失败返回-1
int sigdelset(sigset_t *set, int signum);
- 功能:设置信号集中的某一个信号对应的标志位为0,表示不阻塞这个信号
- 参数:
- set:传出参数,需要操作的信号集
- signum:需要设置不阻塞的那个信号
- 返回值:成功返回0, 失败返回-1
int sigismember(const sigset_t *set, int signum);
- 功能:判断某个信号是否阻塞
- 参数:
- set:需要操作的信号集
- signum:需要判断的那个信号
- 返回值:
1 : signum被阻塞
0 : signum不阻塞
-1 : 失败
*/
/*
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
- 功能:将自定义信号集中的数据设置到内核中(设置阻塞,解除阻塞,替换)
- 参数:
- how : 如何对内核阻塞信号集进行处理
SIG_BLOCK: 将用户设置的阻塞信号集添加到内核中,内核中原来的数据不变
假设内核中默认的阻塞信号集是mask, mask | set
SIG_UNBLOCK: 根据用户设置的数据,对内核中的数据进行解除阻塞
mask &= ~set(也就是先对set取反,再与mask按位与),假设内核中默认的阻塞信号集是mask
SIG_SETMASK:覆盖内核中原来的值
- set :已经初始化好的用户自定义的信号集
- oldset : 保存设置之前的内核中的阻塞信号集的状态,可以是 NULL
- 返回值:
成功:0
失败:-1
设置错误号:EFAULT、EINVAL
int sigpending(sigset_t *set);
- 功能:获取内核中的未决信号集
- 参数:set,传出参数,保存的是内核中的未决信号集中的信息。
*/
参考:链接:https://juejin.cn/post/7250037058684715067