一、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<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) \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<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) \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 <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>#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<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) \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》

linux实时信号与sigqueue函数编程实例相关推荐

  1. linux实时信号的优势,c/c++开发分享Linux和实时信号

    我正在尝试编写在Linux中使用实时信号的简单程序. 但我遇到了奇怪的行为,首先是代码: #include #include #include #include #include"errha ...

  2. Linux信号列表(非实时信号和实时信号)

    列表中,编号为1 ~ 31的信号为传统UNIX支持的信号,是不可靠信号(非实时的),编号为34 ~ 64的信号是后来扩充的,称做可靠信号(实时信号).两者区别: 标准信号的局限性: 1. 阻塞信号可能 ...

  3. Linux捕捉信号机制之(signal,kill)、(sigaction,sigqueue)

    linux下公有64个信号,kill -l 查看一下: 可以看到,缺少了32.33两个未知信号,从这里分界,前面31个信号是不可靠信号,后面的是可靠信号.当进程发生阻塞的时候(一下子发送很多信号),不 ...

  4. 【Linux】Linux的信号

    Linux的信号是一种系统或进程发出的通知,它的主要作用是用来激活信号接收者的一段程序,除此之外,也可以携带少量信息.从实现方式上来看,它是一种用软件构建的中断系统,只不过接收及处理中断请求的不是处理 ...

  5. 【realtime】红帽 RedHat Linux实时内核配置要点全面分析

    CentOS Linux实时性配置要点 rtoax 2021年2月 1. 概要 1.1. 实时性补丁 补丁地址:CentOS 7 - RealTime for x86_64: RealTime: ke ...

  6. linux通过信号回调函数,信号机制的管理结构 - Linux内核中的信号机制_Linux编程_Linux公社-Linux系统门户网站...

    信号只是一个数字,数字为0-31表示不同的信号,如下表所示. 编号 信号名 默认动作 说明 1 SIGHUP 进程终止 终端断开连接 2 SIGINT 进程终止 用户在键盘上按下CTRL+C 3 SI ...

  7. linux 实时时钟(RTC)驱动【转】

    本文转载自:http://blog.csdn.net/yaozhenguo2006/article/details/6820218 这个是linux内核文档关于rtc实时时钟部分的说明,此文档主要描述 ...

  8. linux kill信号列表

    linux kill信号列表 $ kill -l 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL 5) SIGTRAP      6 ...

  9. 红帽Linux故障定位技术详解与实例(1)

    红帽Linux故障定位技术详解与实例(1) 2011-09-28 14:26 圈儿 BEAREYES.COM 我要评论(0) 字号:T | T 在线故障定位就是在故障发生时, 故障所处的操作系统环境仍 ...

最新文章

  1. 为什么 M1 和 Mac 是绝配?
  2. Spring AOP动态代理-切面
  3. 摩托罗拉移动员裁员重点是研发
  4. 再破纪录!ECCV 2020 旷视研究院15篇成果总览
  5. Hulu直播服务难点解析(二):系统设计与实现
  6. stack smash_扶手椅VGUX:Super Smash Bros.Ultimate
  7. C语言超级玛丽菜单模块源码
  8. 从3000米高空,一跃而下…
  9. C# 实现连连看功能
  10. 指针运算符 * 说明
  11. 华为AI音箱更新春节专属技能:对春联 拜年留言
  12. Android中对已安装应用的管理实现
  13. 行人重识别论文阅读14-Learning by Aligning- Visible-Infrared Person Re-identification
  14. grpc编译问题:“C++ versions less than C++11 are not supported.
  15. “多源异构”和“异构同源”定义区分详解
  16. java爬虫京东商品,Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup
  17. 查看mysql数据库最大连接数和已经连接的数量
  18. 小熊开发板STM32工具出现错误Error:an error occured while uploading data from the virtual partition 0xF1
  19. android获取手机的当前OS版本。sdk版本
  20. 2020年现实社会语录,句句道尽人性

热门文章

  1. 利用workerman+html开发简单的在线五子棋对战
  2. 屏蔽浏览器退格键页面后退
  3. Qt下使用QtSql连接sqlite3所遇到的问题总结
  4. 运行txt文本也可能中毒!微软急修“文本病毒”漏洞
  5. 微信小程序_Bug解决_setData失效
  6. Java项目目录结构与解析
  7. linux fedora自定义终端terminal的快捷键
  8. idea报错解决:Cannot start compilation: the output path is not specified for module “XXX“.
  9. kubesphere发布应用到应用商店完整步骤
  10. eureka源码:开启服务注册