文章目录
  1. 发送信号
  2. 信号处理方式
  3. Linux信号
  4. 关于中断系统调用

信号是由用户、系统或者进程发送给目标进程的信息,以通知目标进程某个状态的改变或系统异常。Linux信号可在如下情形产生。

  • 对于前台进程,用户可通过输入特殊的终端字符来向其发送信号;
  • 系统异常(浮点异常,非法内存段访问等);
  • 系统状态变化(如alarm定时器到期将引起SIGALRM信号);
  • 运行kill命令或调用kill函数;

发送信号

在Linux系统中,一个进程向其他进程发送信号的API为kill函数。

1
2
3
4
5
/*
引用方式: #include <signal.h>
返回0: 成功 || 返回-1并设置errno: 失败; EINVAL: 无效的信号 || EPERM: 该进程没有权限发信号给任何一个目标进程 || ESRCH: 目标进程或进程组不存在
*/
int kill(pid_t pid, int sig);

目标进程由pid参数指定,它可能的取值及其含义如下表。

 

Linux定义的信号值都大于0,如果sig取值为0,则kill函数不发送任何信号,但将sig设置为0可以用来检测目标进程或进程组是否存在。不过这种检测方式不可靠:(1)由于进程PID的回绕,可能导致被检测的PID不是我们期望的进程的PID;(2)这种检测方法不是原子操作。

信号处理方式

目标进程需要定义相应的信号处理函数以便在接收到信号后作出相应的处理。信号处理函数的原型如下。

1
2
3
4
5
/*
引用方式: #include <signal.h>
int参数: 指定信号类型
*/
typedef void (* __sighandle_t)(int);

信号处理函数必须可重入,因此信号处理函数严禁调用不安全的函数。

bits/signum.h还定义了信号的两种其他处理方式:SIG_IGN(忽略目标信号)与SIG_DFL(信号的默认处理方式)。信号的默认处理方式有几种:Term(结束进程)、Ign(忽略信号)、Core(结束进程并生成核心转储文件)、Stop(暂停进程)与Cont(继续进程)。

Linux信号

Linux的可用信号都定义在bits/signum.h中,其中包括标准信号与POSIX实时信号。Linux标准信号如下表。

 

重点关注:SIGHUP(控制终端挂起)、SIGPIPE(向读端被关闭的管道或socket连接中写数据)、SIGURG(socket连接上接收到紧急数据)、SIGALRM(由alarm、settimer设置的实时闹钟超时引起)、SIGCHLD(子进程状态发生变化,退出或暂停)。

关于中断系统调用

若程序在执行处于阻塞状态的系统调用时接收到信号,并且我们为信号设置了信号处理函数,则默认情况下系统调用将被中断,并将errno设置为EINTR。程序可以使用sigaction函数为信号设置SA_RESTART标志自动重启被中断的系统调用。

对于默认行为是暂停进程的信号(SIGSTOP、SIGTTIN),若程序未设置相应的信号处理函数,这些信号仍然可以中断一些系统调用(connect、epoll_wait)。这是Linux所特有的。