Linux 信号

类似于嵌入式中的软中断。由内核发出信号告知进程,且不进行排队。这意味着当多个相同信号同时到来的时候进程将只会执行一次信号处理函数。

几个重要的信号

SIGPIPE 管道中止,当写入无人读取的管道时产生该信号,默认终止进程
SIGCHLD 子进程结束或者停止时发送
SIGALRM 定时器信号,以秒为单位,默认终止进程
SIGUSR1/SIGUSR2 自定义信号,默认终止信号
SIGINT 键盘输入的退出信号 ctrl+’'
SIGOUIT 键盘输入的退出信号 ctrl+c
SIGHUP 控制终端的挂起信号 ctrl+z

SIGPIPE

网络程序必须要处理SIGPIPE信号,否则当客户端退出的时候服务器仍然向管道中发送数据,会造成crash

SIGCHLD

处理僵尸进程

僵尸进程是已经死亡的进程,资源已经释放但是任然占用一个进程号.父进程没有处理SIGCHLD信号或者wait/waitpid()后,子进程结束后没有对子进程进行处理会导致僵尸进程

发送信号

  1. 硬件方式: ctrl+c等
  2. 软件方式: kill api

安装信号

简单方式:

signal(int sig,void (*func)(int));

高级方式:

 int sigaction(int sig,const struct sigaction *act,struct sigaction * oact)

struct sigaction{
     void (*sa_handler)(int);
	void (*sa_sigaction)(int ,siginfo_t *,void *);//处理函数
	sigset_t sa_mask; //掩码  在处理函数中对于哪个信号会进行处理,置位表示屏蔽
	int sa_flags; //根据SA_SIGINFO 标记选择处理函数 
	void (*sa_restorer)(void); //设置为null,一般不用

};

在服务器程序中,如果主程序进入了一个中断调用退出后,accept 会返回EINTR错误(被中断的系统调用),这时候我们需要设置sa_flags| = SA_RESTART标志,这个标志是自动重启被中断的系统调用,这样我们的accept 就不会返回错误.

但是对于这一类慢系统调用(accept、select)来说,最好手动重启,即error==EINTR时候重新循环,这样时为了考虑到移植性,在一些系统并非支持SA_RESTART