一、sigqueue函数
功能:新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用。
原型:int sigqueue(pid_t pid, int sig, const union sigval value);
参数:
sigqueue的第一个参数是指定接收信号的进程id,第二个参数确定即将发送的信号,第三个参数是一个联合数据结构union sigval,指定了信号传递的参数,即通常所说的4字节值。
返回值:成功返回0,失败返回-1
typedef union sigval
{
int sival_int;
void *sival_ptr;
}sigval_t;
sigqueue()比kill()传递了更多的附加信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组。
写两个小程序测试一下:
首先是接收信号:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
/*************************************************************************
> File Name: process_.c > Author: Simba > Mail: dameng34@163.com > Created Time: Sat 23 Feb 2013 02:34:02 PM CST ************************************************************************/ #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<signal.h> #define ERR_EXIT(m) \ void handler(int, siginfo_t *, void *); int main(int argc, char *argv[]) if (sigaction(SIGINT, &act, NULL) < 0) for (; ;) return 0; } void handler(int sig, siginfo_t *info, void *ctx) } |
在前面的《信号捕捉与sigaction函数》中说过,sa_sigaction与SA_SIGINFO要配合使用,如上所示,siginfo_t 结构体也可以参见这篇文章。
然后是信号发送:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
/*************************************************************************
> File Name: process_.c > Author: Simba > Mail: dameng34@163.com > Created Time: Sat 23 Feb 2013 02:34:02 PM CST ************************************************************************/ #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<signal.h> #define ERR_EXIT(m) \ int main(int argc, char *argv[]) pid_t pid = atoi(argv[1]); //字符串转换为整数 return 0; } |
测试如下:
先运行recv程序:
simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./sigqueue_recv
再ps出recv进程的pid,然后运行send程序:
simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./sigqueue_send 3323
则recv进程会输出一条recv语句,当然我们也可以ctrl+c 给自己发送信号,如下所示,结果是一样的。
recv a sig=2 data=100 data=100
^Crecv a sig=2 data=100 data=100
^Crecv a sig=2 data=100 data=100
......................................................
需要提醒一下的是siginfo_t 结构体的两个参数(int si_int; /* POSIX.1b signal */ void
*si_ptr; /* POSIX.1b signal */)的值也会与si_value 一致,取决于发送的是sival_int 还是 sival_ptr。
二、实时信号与不可靠信号的区别
下面通过程序来说明区别,主要就是实时信号支持排队不会丢失。(实时信号还有一个特点,即到达的顺序是可以保证的)
先是recv程序:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#include <unistd.h>
#include <sys/stat.h> #include <sys/wait.h> #include <sys/types.h> #include <fcntl.h> #include <stdlib.h> #define ERR_EXIT(m) \ void handler(int); int main(int argc, char *argv[]) sigset_t s; if (sigaction(SIGRTMIN, &act, NULL) < 0) if (sigaction(SIGUSR1, &act, NULL) < 0) void handler(int sig) |
在主函数中将SIGINT和SIGRTMIN信号加入信号屏蔽字,只有当接收到SIGUSR1信号时才对前面两个信号unblock。需要注意的是如《信号的未决与阻塞》中说的一样:如果在信号处理函数中对某个信号进行解除阻塞时,则只是将pending位清0,让此信号递达一次(同个实时信号产生多次进行排队都会抵达),但不会将block位清0,即再次产生此信号时还是会被阻塞,处于未决状态。
接着是send程序:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
/*************************************************************************
> File Name: sigrtime_send.c > Author: Simba > Mail: dameng34@163.com > Created Time: Sat 23 Feb 2013 02:34:02 PM CST ************************************************************************/ #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<signal.h> #define ERR_EXIT(m) \ int main(int argc, char *argv[]) pid_t pid = atoi(argv[1]); //字符串转换为整数 return 0; } |
先是运行recv程序:
simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./sigrtime_recv2
接着ps出recv进程的pid,运行send程序:
simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./sigrtime_send 4076
在send程序中连续各发送了SIGINT和SIGRTMIN信号3次,接着睡眠3s后使用kill函数发送SIGUSR1信号给recv进程,此时recv进程会输出如下:
recv a sig=34
recv a sig=34
recv a sig=34
recv a sig=2
即实时信号支持排队,3个信号都接收到了,而不可靠信号不支持排队,只保留一个信号。
参考:《APUE》