linux实时信号与sigqueue函数编程实例
一、sigqueue函数
功能:新的发送信号系统调用,主要是针对实时信号提出的支持信号带有参数,与函数sigaction()配合使用。
原型:int sigqueue(pid_t pid, int sig, const union sigval value);
第一个参数是指定接收信号的进程id;
第二个参数确定即将发送的信号;
第三个参数是一个联合数据结构union sigval,指定了信号传递的参数,即通常所说的4字节值。
typedef union sigval { int sival_int; void *sival_ptr; }sigval_t;
返回值:成功返回0,失败返回-1
sigqueue()比kill()传递了更多的附加信息,但sigqueue()只能向一个进程发送信号,而不能发送信号给一个进程组。
接收程序:
#include
#include
#include
#include
#include
#include
#include
#include
#include#define ERR_EXIT(m) \do { \perror(m); \exit(EXIT_FAILURE); \} while(0)void handler(int, siginfo_t *, void *); int main(int argc, char *argv[])
{struct sigaction act;act.sa_sigaction = handler; //sa_sigaction和sa_handler都是结构体sigaction的成员,只能取其一,当设置了sa_sigaction就 //不用设置sa_handler了,sa_sigaction多用于实时信号,可以保存信息sigemptyset(&act.sa_mask);act.sa_flags = SA_SIGINFO; // 设置标志位后可以接收其他进程// 发送的数据,保存在siginfo_t结构体中if (sigaction(SIGINT, &act, NULL) < 0)ERR_EXIT("sigaction error");for (; ;)pause();return 0;}void handler(int sig, siginfo_t *info, void *ctx)
{printf("recv a sig=%d data=%d data=%d\n",sig, info->si_value.sival_int, info->si_int);}-----------------------------------------------------
struct sigaction
{void (*sa_handler)(int);sigset_t sa_mask; int sa_flags; void (*sa_sigaction)(int, siginfo_t *, void *);
};
如果不设置sa_flags的话,初始化为void (*sa_handler)(int);这个就和signal差不多了哦,void handler(int signo);如果设置了sa_flags=SA_SIGINFO则,初始化为void (*sa_sigaction)(int, siginfo_t *, void *);
其中siginfo、context这个结构体的定义参见APUE(Advanced Programming in the UNIX Environment),即《UNIX环境高级编程》,上述例子中用
void handler(int signo, siginfo_t* info, void* context);作为信号处理函数注意两者不可以同时使用...
发送程序:
#include
#include
#include
#include
#include
#include
#include
#include
#include#define ERR_EXIT(m) \do { \perror(m); \exit(EXIT_FAILURE); \} while(0)int main(int argc, char *argv[])
{if (argc != 2){fprintf(stderr, "Usage %s pid\n", argv[0]);exit(EXIT_FAILURE);}pid_t pid = atoi(argv[1]); //字符串转换为整数union sigval val;val.sival_int = 100;sigqueue(pid, SIGINT, val); //只可以发信号给某个进程,而不能是进程组return 0;
}
终端打印结果:
recv a sig=2 data=100 data=100
实时信号收发编程
接受程序:
#include
#include
#include
#include
#include #include
#include
#include
#include
#include #define ERR_EXIT(m) \do \{ \perror(m); \exit(EXIT_FAILURE); \} while(0)void handler(int);int main(int argc, char *argv[])
{struct sigaction act;act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigset_t s;sigemptyset(&s);sigaddset(&s, SIGINT);sigaddset(&s, SIGRTMIN);sigprocmask(SIG_BLOCK, &s, NULL);if (sigaction(SIGINT, &act, NULL) < 0)ERR_EXIT("sigaction error");if (sigaction(SIGRTMIN, &act, NULL) < 0)ERR_EXIT("sigaction error");if (sigaction(SIGUSR1, &act, NULL) < 0)ERR_EXIT("sigaction error");for (;;)pause();return 0;
}void handler(int sig)
{if (sig == SIGINT || sig == SIGRTMIN)printf("recv a sig=%d\n", sig);else if (sig == SIGUSR1){sigset_t s;sigemptyset(&s);sigaddset(&s, SIGINT);sigaddset(&s, SIGRTMIN);sigprocmask(SIG_UNBLOCK, &s, NULL);}
}
在主函数中将SIGINT和SIGRTMIN信号加入信号屏蔽字,只有当接收到SIGUSR1信号时才对前面两个信号unblock。需要注意的是如《信号的未决与阻塞》中说的一样:如果在信号处理函数中对某个信号进行解除阻塞时,则只是将pending位清0,让此信号递达一次(同个实时信号产生多次进行排队都会抵达),但不会将block位清0,即再次产生此信号时还是会被阻塞,处于未决状态。
发送程序:
#include
#include
#include
#include
#include
#include
#include
#include
#include#define ERR_EXIT(m) \do { \perror(m); \exit(EXIT_FAILURE); \} while(0)int main(int argc, char *argv[])
{if (argc != 2){fprintf(stderr, "Usage %s pid\n", argv[0]);exit(EXIT_FAILURE);}pid_t pid = atoi(argv[1]); //字符串转换为整数union sigval val;val.sival_int = 100;sigqueue(pid, SIGINT, val); // 不可靠信号不会排队,即会丢失sigqueue(pid, SIGINT, val);sigqueue(pid, SIGINT, val);sigqueue(pid, SIGRTMIN, val); //实时信号会排队,即不会丢失sigqueue(pid, SIGRTMIN, val);sigqueue(pid, SIGRTMIN, val);sleep(3);kill(pid, SIGUSR1);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》
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
