6.8.3 sigqueue函数
在信号发送的方式当中,sigqueue算是后起之秀,传统的信号多用signal/kill这两个函数搭配,完成信号处理函数的安装和信号的发送。
后来因为signal函数的表达力有限,控制不够精准,所以引入了sigaction函数来负责信号的安装
与其对应的是,引入了sigqueue函数来完成实时信号的发送。
当然了,sigqueue函数也能发送非实时信号。
sigqueue函数的接口定义如下:
int sigqueue(pid_t pid, int sig, const union sigval value);
sigqueue函数拥有和kill函数类似的语义,也可以发送空信号(信号0)来检查进程是否存在。
和kill函数不同的地方在于,它不能通过将pid指定为负值而向整个进程组发送信号。
比较有意思的是函数的第三个入参,它指定了信号的伴随数据(或者称为有效载荷,payload),该参数的数据类型是联合体,定义代码如下:
union sigval {
int sival_int;
void *sival_ptr;
};
通过指定sigqueue函数的第三个参数,可以传递一个int值或指针给目标进程。
考虑到不同的进程有各自独立的地址空间,传递指针到另一个进程几乎没有任何意义。
因此sigqueue函数很少传递指针(sival_ptr),大多是传递整型(sival_int)。
注意 :
尽管跨进程使用sigval中的指针sival_ptr没有任何意义,但sival_ptr字段并非百无一用。该字段可用于使用sigval联合体的其他函数中,如POSIX计时器的timer_create函数和POSIX消息队列中的mq_notify函数。
sigval联合体的存在,扩展了信号的通信能力。
一些简单的消息传递完全可以使用sigqueue函数来进行。
比如,通信双方事先定义某些事件为不同的int值,通过sigval联合体,将事件发送给目标进程。目标进程根据联合体中的int值来区分不同的事件,做出不同的响应。但是这种方法传递的消息内容受到了限制,不容易扩展,所以不宜作为常规的通信手段。
下面的例子会使用sigqueue函数向目标进程发送信号,其中目标进程、信号值和发送次数都可指定,发