今天继续对信号进行学习,开始正入正题:

sigaction函数:
安装信号之前我们已经学过一个函数:signal,它最早是在unix上出现的,它是对不可靠信号进行安装的,之后出现了可靠信号和实时信号,所以新的安装函数sigaction函数就出现了,它的原形如下:
sigaction结构体:
通过man手册来查看一下它的说明:
关于这些说明,下面会用实验一一来阐述的,所以可以先了解一下既可。
sigaction示例:
下面先来看一下它的简单用法,也就是实现signal相同的功能来安装一个SIGINT信号:
#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 sig);int main(int argc, char *argv[])
{struct sigaction act;//安装信号时需要传参act.sa_handler = handler;sigemptyset(&act.sa_mask);//先将sa_mask清空,关于这个属性的用法之后实验再说明act.sa_flags = 0;//同样将sa_flags设为0,这个实现不需要关心,之后会说明if (sigaction(SIGINT, &act, NULL) < 0)//安装信号ERR_EXIT("sigaction error\n");for (;;)pause();return 0;
}void handler(int sig)
{printf("recv a sig=%d\n", sig);
}

编译运行:

实际上,对于signal这个安装函数是在可靠的机制之上进行的,也就是说可以认为它是通过sigaction来实现的,所以接下来,用sigaction来模拟signal函数的行为
#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 sig);
__sighandler_t my_signal(int sig, __sighandler_t handler);//这跟signal的信号安装函数声明一样,实现自己的signalint main(int argc, char *argv[])
{
/*struct sigaction act;act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;if (sigaction(SIGINT, &act, NULL) < 0)ERR_EXIT("sigaction error\n");
*/my_signal(SIGINT, handler);for (;;)pause();return 0;
}__sighandler_t my_signal(int sig, __sighandler_t handler)
{struct sigaction act;struct sigaction oldact;//保存最初的行为act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;if (sigaction(sig, &act, &oldact) < 0)return SIG_ERR;return oldact.sa_handler;
}void handler(int sig)
{printf("recv a sig=%d\n", sig);
}

效果也是一样的,从以上代码可以看出,sigaction功能比signal要强大说了,其中有两个参数需要说明一下:

其中sa_handler只适合不可信号的安装,也就是说不可信号的安装不能用sa_sigaction,这个需要注意。

下面来说明一下sa_mask这个属性是什么效果,然后再回头来看下文字说明:

#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 sig);int main(int argc, char *argv[])
{struct sigaction act;act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;if (sigaction(SIGINT, &act, NULL) < 0)ERR_EXIT("sigaction error");for (;;)pause();return 0;
}void handler(int sig)
{printf("recv a sig=%d\n", sig);sleep(5);//故意睡眠5秒是为了看在执行期间按了ctrl+\就能立马响应退出信号
}

编译运行:

可以看到,在执行信号处理函数期间,按ctrl+c时,并没有等待sleep5秒完之后,再执行退出动作,而是立马执行了,那能不能改变这种默认,也就是必须得等sleep5秒后再执行退出动作,答案是当然可以的,sa_mask属性就派上用场了:

结果如下:

从实验结果来看,在执行信号处理时,多次按了ctrl+c退出信号,并未立马执行退出动作,而是等执行完了才退出的,这也就是sa_mask的作用,实际上也就是上节学习的信号屏蔽字,不太清楚的可以参考博文:http://www.cnblogs.com/webor2006/p/3751210.html

思考一个问题:sa_mask的作用跟之前学的进程中的信号屏蔽字可以对其信号进行阻塞有什么区别呢?

#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 sig);int main(int argc, char *argv[])
{struct sigaction act;act.sa_handler = handler;sigemptyset(&act.sa_mask);//sigaddset(&act.sa_mask, SIGQUIT);//将其sa_mask注册去掉,也就是清零了act.sa_flags = 0;sigset_t s;sigemptyset(&s);sigaddset(&s, SIGINT);sigprocmask(SIG_BLOCK, &s, NULL);//这就是之前学的,将SIGINT加入到进程的屏蔽字中if (sigaction(SIGINT, &act, NULL) < 0)ERR_EXIT("sigaction error");for (;;)pause();return 0;
}void handler(int sig)
{printf("recv a sig=%d\n", sig);sleep(5);
}

编译运行:

这时可以看到,信号被阻塞而压缩就不会执行处理函数了,这也是之前学过时的现象,从实验可以总结出:

sa_mask中指定的掩码也可以阻塞信号,它阻塞的信号是指函数在执行的过程当中,如果发生了在掩码级中指定的信号,信号将被阻塞,直到handler返回,这些信号才能被递达;

sigprocmask它所阻塞的信号表示将这些集合中的信号添加到进程信号屏蔽字当中,这些信号就不能被递达了,既使它发生了。

好了,今天的内容学到这,虽说内容不多,但是还是比较生涩的,下回继续!

转载于:https://www.cnblogs.com/webor2006/p/3753987.html

linux系统编程之信号(五)相关推荐

  1. linux系统发送信号的系统调用是,linux系统编程之信号:信号发送函数sigqueue和信号安装函数sigaction...

    信号发送函数sigqueue和信号安装函数sigaction sigaction函数用于改变进程接收到特定信号后的行为. sigqueue()是比较新的发送信号系统调用,主要是针对实时信号提出的(当然 ...

  2. 【Linux系统编程】信号 (下)

    00. 目录 文章目录 00. 目录 01. 信号集 02. 信号阻塞集 03. sigaction函数 04. 附录 01. 信号集 为了方便对多个信号进行处理,一个用户进程常常需要对多个信号做出处 ...

  3. 【Linux系统编程】信号 (上)

    00. 目录 文章目录 00. 目录 01. 信号概述 02. 信号编号 03. 信号产生方式 04. kill发送信号 05. pause等待信号 06. 信号处理方式 07. 信号处理函数 08. ...

  4. linux系统编程之信号(一):信号基本概述

    一.为了理解信号,先从我们最熟悉的场景说起: 1. 用户输入命令,在Shell下启动一个前台进程. 2. 用户按下Ctrl-C,这个键盘输入产生一个硬件中断. 3. 如果CPU当前正在执行这个进程的代 ...

  5. linux系统编程之信号(四):信号的捕捉与sigaction函数

    一.内核如何实现信号的捕捉 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号.由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 1. 用户程序注册了SI ...

  6. Linux系统编程(二)–信号

    文章目录 1 Hello signal 1.1 hello signal 程序 1.2 向 hello signal 发信号 1.3 招待你的"客人" 1.3.1 signal 函 ...

  7. linux系统编程之信号(signal)的使用方法案例

    信号处理过程: 中断源->中断屏蔽->保护现场->中断处理程序->中断恢复 信号称为软中断 //kill -l 查看所有signal信号 共计64个信号 //man 7 sig ...

  8. Linux系统编程47 信号 - setitimer(),优先使用setitimer()计时

    NAMEgetitimer, setitimer - get or set value of an interval timerSYNOPSIS#include <sys/time.h>i ...

  9. linux 可定义信号数,Linux系统编程(20)——信号基本概念

    信号及信号来源 信号是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知 ...

最新文章

  1. aligned_storage简单学习
  2. ubuntu中解决无法调节屏幕亮度的问题
  3. [消息]C++ Connections 在拉斯维加斯召开年会
  4. java多线程意义_Java多线程学习之多线程的概念及意义
  5. Java Number Math 类
  6. java十进制转十六进制
  7. 关于Swift中的forEach(_:)和for-in loop
  8. python 多线程 入门
  9. android屏幕同步到macbook,Mirror for Android TV for Mac(屏幕和声音镜像到Android TV的工具)...
  10. library/adodb/adodb.inc.php,ADOdb Library for PHP
  11. Poker2 的爱与愁-入手两周,小小体会
  12. 静态测试和动态测试有何区别
  13. 透彻解读mysql的可重复读、幻读及实现原理
  14. 如何让你的程序员不要厌倦工作?
  15. 重构:改善既有代码的设计(评注版)
  16. 网易蓝牙耳机怎么切换双耳_2020双十一蓝牙耳机怎么选?有哪些便宜又好用的蓝牙耳机?有哪些适合学生党的蓝牙耳机?《选购指南》...
  17. ios上传ipa:Xcode导入ipa上传至App Store
  18. 实验吧WEB CTF 猫抓老鼠 全网最简单易懂的解题方法
  19. 1881:【14NOIP提高组】生活大爆炸版石头剪子布
  20. 【毕业设计】机器视觉火车票识别系统 - python 深度学习

热门文章

  1. docker from指令的含义_Docker 镜像常用命令
  2. POST 请求出现异常!java.io.IOException: Server returned HTTP response code: 400 for URL
  3. hibernate映射文件出现should be mapped with insert=“false“ update=“false“
  4. 【w3cschool】C语言复习
  5. 【LOJ101】最大流(Edmonds-Karp)
  6. checkbox 点击搜索失去焦点_早些年植入三焦点晶体矫正老花的人,现在怎么样了?...
  7. 根据mysql生成数据库设计文档_通过navicat工具导出数据库的word格式的设计文档...
  8. Shuffle Cards(Rope大法)将一段区间的数字整体搬动
  9. Photoshop1:入门实用技巧
  10. OpenGL基础3:渲染管线