Linux系统里的sigqueue函数支持信号携带参数,函数原型如下:
#include <signal.h>
int sigqueue(pid_t pid, int sig, const union sigval value);
参数value是一个共用体,定义如下:
union sigval{
int sival_int;
void *sival_ptr;
};
我注意到这个共用体中有一个是指针,就想到,进程间能不能传递指针呢,用程序验证
// 示例利用信号传递数据,本程序发送数据
// 选项-d 后跟待传递的数据,选项-s 后跟待发送的信号,选项-p 后跟目的进程ID
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char ** argv)
{
union sigval value;
int signum = SIGTERM; // 默认发送SIGTERM
pid_t pid;
int i;
/*初始化*/
value.sival_int = 0;
/*检查参数的个数*/
if (argc != 3 && argc != 5 && argc != 7) {
printf("./send_data_signo <-d data> <-s signum> [-p][data]\n");
exit(1);
}
/*从命令行参数解析出信号编号、PID以及待传递的数据*/
for (i=1; i<argc; i++) {
if (!strcmp(argv[i], "-d")) {
value.sival_ptr = argv[i+1]; //指针指向参数中的字符串
continue;
}
if (!strcmp(argv[i], "-s")) {
signum = atoi(argv[i+1]);
continue;
}
if (!strcmp(argv[i], "-p")) {
pid = atoi(argv[i+1]);
continue;
}
}
/*利用sigqueue给pid发送信号signum,并携带数据value*/
if (sigqueue(pid, signum, value) < 0) {
perror("sigqueue");
exit(1);
}
return 0;
}
// 示例利用信号传递数据,本程序接收数据
#include <signal.h>
#include <stdio.h>
/*三参数的信号处理程序*/
void handler_sigint(int signo, siginfo_t *siginfo, void * pvoid)
{
printf("recv SIGINT, the data value is:%s\n",(char *) siginfo->si_ptr);
}
int main()
{
struct sigaction act;
/*赋值act结构*/
act.sa_sigaction = handler_sigint;
act.sa_flags = SA_SIGINFO; // 指定使用三参数的信号处理函数
/*安装信号处理函数*/
sigaction(SIGINT, &act, NULL);
while(1)
;
return 0;
}
经过编译后运行如下:
在第一个终端中:
#./recv_data_signo
在第二个终端:
#ps -a
查看进程号,然后
#./send_data_signo -s 2 -d hello -p 4832
第一个终端显示:
Segmentation fault
所谓的Segmentation Fault(段错误)就是指访问的内存超出了系统所给这个程序的内存空间
可见,即使成功传递了指针,但是在另一进程里仍然不能引用。
我们试一试同一个进程的情况.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void handler_sigint(int signo, siginfo_t *siginfo, void * pvoid)
{
printf("recv SIGINT, the data value is:%s\n", (char *)(siginfo->si_ptr));
}
int main(int argc, char ** argv)
{
struct sigaction act;
union sigval value;
int signum = SIGTERM;
pid_t pid;
int i;
act.sa_sigaction = handler_sigint;
act.sa_flags = SA_SIGINFO;
sigaction(SIGINT, &act, NULL);
value.sival_ptr = NULL;
if (argc != 3 && argc != 5 ) {
printf("./send_data_signo <-d data> <-s signum> \n");
exit(1);
}
for (i=1; i<argc; i++) {
if (!strcmp(argv[i], "-d")) {
value.sival_ptr = argv[i+1];
continue;
}
if (!strcmp(argv[i], "-s")) {
signum = atoi(argv[i+1]);
continue;
}
}
pid = getpid();
if (sigqueue(pid, signum, value) < 0) {
perror("sigqueue");
exit(1);
}
return 0;
}
编译运行:
#./send_data_signo -s 2 -d hello
recv SIGINT, the data value is:hello
同一个进程里能正常传递指针
参考文献:《Linux c编程实战》童永清