今天继续学习信号相关的知识,主要还是学习sigqueue另外信号发送函数,并配合上节学习的sigaction的用法,进入正题:

sigqueue函数:
sigval联合体:
实际上sigval参数是用来进程间通信用的,实际上信号是一个很古老的进程间通信的一种手段,通过这个参数,可以从一个进程发送到另外一个进程,并且可以附带参数。下面以实际代码来说明sigqueue是如何传递数据的:
这里需要编写一个进程发送信号和一个进程接收信号来说明sigqueue:
接收信号:
要想接收信号数据,则需要在sigaction上加入flag,也就是上节当中遗漏的一个知识点,查看man帮助:
 
 
另外,还得注意,如果要想接收信号,需要用到sigaction的另外一个处理函数:
 
具体接收代码如下sigaction_recv.c:
#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() void handler(int, siginfo_t *, void *);//需要用带多个参数的handler int main(int argc, char *argv[])
{
struct sigaction act;
act.sa_sigaction = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;//设置该flags可以接收其它进程传过来的信号 if (sigaction(SIGINT, &act, NULL) < )
ERR_EXIT("sigaction error"); for (;;)
pause();
return ;
} void handler(int sig, siginfo_t *info, void *ctx)
{
printf("recv a sig=%d data=%d\n", sig, info->si_value.sival_int);//它实际上就是sigqueue的sigval联合体,并打印出传过来的整型值
}
 
发送信号:
编写一个通过sigqueue向某进程发送信号并携带数据来达到进程间通讯的目的:
sigaction_send.c:
编译运行:
先运行接收信号的程序:
再运行进程发送程序,向该接收进程发送信号,先找到该接收进程号:
然后进行我们写的信号发送程序:
另外,数据的接收还可以用这种方式来打印:
输出如下:
为啥可以这样写呢?查看sigaction的帮助:
所以通过这种方式就能达到进程间通讯的目的。
接下来再演示一个不可靠与可靠信号的一个问题:可靠信号支持排队,不可靠信号是不支持排队的
验证方法:
① 写一个接收程序,里面注册一个可靠信号,一个不可靠信号,并将其加入屏蔽字中进行阻塞,然后再注册一个解除这两个信号阻塞的信号,程序如下:
sigaction_recv.c:
#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() void handler(int); int main(int argc, char *argv[])
{
struct sigaction act;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = ; sigset_t s;
sigemptyset(&s);
sigaddset(&s, SIGINT);
sigaddset(&s, SIGRTMIN);
sigprocmask(SIG_BLOCK, &s, NULL);//将这两个信号都加入屏蔽字当中进行阻塞
if (sigaction(SIGINT, &act, NULL) < )//注册一个不可靠信号
ERR_EXIT("sigaction error"); if (sigaction(SIGRTMIN, &act, NULL) < )//注册一个可靠信号
ERR_EXIT("sigaction error"); if (sigaction(SIGUSR1, &act, NULL) < )//注册一个解除阻塞信号的信号
ERR_EXIT("sigaction error");
for (;;)
pause();
return ;
} void handler(int sig)
{
if (sig == SIGINT || sig == SIGRTMIN)
printf("recv a sig=%d\n", sig);
else if (sig == SIGUSR1)
{//当接收到SIGUSR1信号时,则解除阻塞,这时被阻塞的SIGINT,SIGRTMIN信号就变为递达状态了,这时就可以观察两者的区别了
sigset_t s;
sigemptyset(&s);
sigaddset(&s, SIGINT);
sigaddset(&s, SIGRTMIN);
sigprocmask(SIG_UNBLOCK, &s, NULL);
}
}

② 编写一个发送信号的程序,里面发送多个SIGINT可靠信号,多个SIGTMIN不可靠信号,并且延时几秒之后,再将发送SIGUSR1信号解除绑定,最终观察看SIGINT收到了几个,SIGTMIN收到了几个,具体代码如下:

sigaction_send.c:

#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() int main(int argc, char *argv[])
{
if (argc != )
{
fprintf(stderr, "Usage %s pid\n", argv[]);
exit(EXIT_FAILURE);
} pid_t pid = atoi(argv[]);
union sigval v;
v.sival_int = ;
sigqueue(pid, SIGINT, v);
sigqueue(pid, SIGINT, v);
sigqueue(pid, SIGINT, v);//发送三个SIGINT不可靠信号 sigqueue(pid, SIGRTMIN, v);
sigqueue(pid, SIGRTMIN, v);
sigqueue(pid, SIGRTMIN, v);//发送三个SIGTMIN可靠信号 sleep();//休眠3秒,目的是让其多个信号进行阻塞 kill(pid, SIGUSR1);//发送一个SIGUSR1信号进行解除阻塞,改用kill来发送,当然也可用sigqueue啦
return ;
}

编译运行:

从运行结果来看,经过3秒之后,34号信号,也就是SIGRTMIN信号接收了三次,而2号信号SIGINT信号只接收了一次,所以也论证了可靠信号是支持排队的,而不可靠信号是不支持排队的

关于sigaction还有很多其它的用法,这个之后有需求再进行探索,好了,今天的内容就学到这,下节见!

最新文章

  1. Angular初步
  2. 【代码笔记】iOS-圆角矩形
  3. 20145320《Java程序设计》第三次实验报告
  4. 自学silverlight 5.0
  5. MongoDB学习笔记——聚合操作之聚合管道(Aggregation Pipeline)
  6. Ext学习-基础组件介绍
  7. [iOS基础控件 - 6.12.1] QQ菜单管理 UITabBarController 控制器管理
  8. 第二章 Qt常用工具的介绍
  9. springmvc的几点见解
  10. MVC +EF+linq 多表联查
  11. 题解 P3871 【[TJOI2010]中位数】
  12. java替换ascii表字符
  13. JS-词法作用域 作用域链
  14. python selenium-webdriver 定位frame中的元素 (十三)
  15. 移动端iscroll实现日期选择
  16. 学习Mysql过程中拓展的其他技术栈:Docker入门介绍
  17. classpath路径配置
  18. CSS| text文本属性
  19. 使用Numpy验证Google GRE的随机选择算法
  20. idea导出war包并在tomcat上部署

热门文章

  1. Java之浮点数运算
  2. 使用transform后z-index失效的解决方法
  3. jqGrid设置单选
  4. OpenGL入门学习--超级好的资料
  5. ply2obj
  6. WIP*更新生产批详细信息行产品配料
  7. Word 自带公式编写多行公式时在任意位置对齐 -- 含视频教程(10)
  8. MySQL数据库-表操作-SQL语句(一)
  9. Codeforces 1239B. The World Is Just a Programming Task (Hard Version)
  10. CCF 2016-04-2 俄罗斯方块