1.发送信号:kill函数/命令
kill(pid,信号):pid>0 发送给指定进程信号 pid=0发送给本进程组内的其他进程信号
pid=-1 信号发送给处init进程外所有的进程,但是发送者需要拥有对所有目标进程发送信号的权限
Pid<-1信号发送给组id为-pid的进程组中的所有成员
信号的值一般都大于0若信号取值为0 kill不发送任何信号 但是sig=0可以用来检测目标进程或者进程组是否存在,因为检查工作总是在信号发送之前就执行,但是并不可靠。因为进程pid的回绕,可能导致检测的进程不是我们的目标进程,另一方面,该操作并不是原子操作。
kill函数成功返回0 失败返回-1 并设置errno
2.signal函数:两个参数,要捕获的信号类型和信号处理函数的函数指针
sigaction函数三个参数,更滑健壮的函数接口 要捕获的信号类型,信号处理方式和输出信号先前的处理方式(如果不为NULL的话)
后两个参数都是struct sigaction结构体类型的指针。该结构体中sa_hander指定信号处理函数 sa_mask成员用于设置进程的信号掩码()确切的说是在进程 原有信号掩码的基础上增加信号掩码,以指定哪些信号不能发送给本进程,是一个信号集类型的参数
3.设置进程信号掩码字后,被屏蔽的信号将不能被进程接收。如果给进程发送一个被屏蔽的信号,则操作系统将该信号设置为进程的一个被挂起的信号。如果取消屏蔽则会立即接收到。
sigpending获取进程当前被挂起的信号集
4.信号是一种异步事件,信号处理函数和程序的主循环是两条不同的执行路线。
但是由于信号处理函数应该是可重入的,不然很容易引发一些竞态条件。也因此信号处理函数中严禁调用不安全的函数
异步的方式代表信号处理函数需要尽可能快的执行完毕,以确保该信号不被屏蔽太久。屏蔽的原因就是因为为了避免之前所说的竞态条件的产生,所以在信号处理期间系统不会再次触发它。
解决这种问题的一种常见方法就是:把信号的主要处理逻辑放在程序的主循环中,当信号处理函数被触发只是建的通知主循环接收信号并传入信号。主循环根据接收到的信号执行相应的逻辑代码
以管道的方式,信号处理函数爱管道的写端写入信号值,主循环则在读端通过IO复用来监听是否有信号可读
5.常见信号
SIGPIPE:默认情况下,往一个读端关闭的管道或者socket连接中写入数据将会引发SIGPIPE信号。一般需要在代码中捕获或者处理该信号,或者忽略它,因为程序接收到SIGPIPE信号的默认行为是结束进程,而我们不希望因为错误的写操作而导致进程退出 。
我们可以使用
①send函数的MSG_NOSIGNAL标志来禁止写操作触发SIGPIPE信号。在这种情况下,应该使用send函数反馈的errno值来判断管道或者socket连接的读端是否关闭。
②利用IO复用系统调用检测socket连接的读端是否已经关闭。以poll为例,当管道读端关闭时,写端文件描述符上的POLLHUP事件将被触发;当socket连接被对方关闭时,socket上的POLLRDHUP事件将被触发。