APUE学习之------------信号
在学习一个东西的时候我总是喜欢去问这样做的理由是什么?也喜欢去究竟他的历史。从中你可以发现所有的设计都在不断改进出来的,从来就没有一个设计是一开始就是完美的。好比是人,之初,性也许是善的,如果我们不通过后天的学习去让自己的心灵完美的话,他就只停留在了人的初级阶段了。
对于信号(signal)也是如此,硬件的中断中得出他的模型,然后不断的的去完善它。当一个事件发生时内核就会对该进程发送相应的信号,比如,内存错误了就是发送SIGSEGV,这个也就是我们常看到的段错误。再比如当我们做除零操作是就会发送SIGFPE。具体的信号定义的话可以参照http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC336 。下面就来看看具体的代码函数。
1.信号的注册。
typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
这里不管你在做什么事情,产生一个软中断后内核deliver一个信号给进程,然后进程马上中止当前的任务去做信号处理相关的动作,但是我之前的事情也不能丢掉啊,等你做完信号处理的紧急的事情之后你应该继续把之前的时候完成 吧。于是乎就出现了可重入函数,等执行完信号处理函数之后,进程再次的回到之前的处理位置接着执行。关于那些事可重入的函数可以参考http://man7.org/linux/man-pages/man7/signal.7.html. 一个解决方案的引入通常带入了另外一个问题,如果这个函数是不可重入的呢?,在某一段代码中我们接收到信号,但是,我们又不想中断当前的函数?直接忽略这个型号吗?NO,操作系统又给我们提供了一些和信号集相关的函数。如果一段代码中你不想接受到某些信号你可以先将其阻挡在外,等处理完之后可以看下该型号是不是在block列表里,如果一个信号在被阻挡的列表了你可以对其单独的处理。这里的处理正的和生活中的某些处理很相似。看来我们的程序设计也是来源于生活的。下面使一些与之相关的函数:
int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signum); int sigdelset(sigset_t *set, int signum); int sigismember(const sigset_t *set, int signum);
int sigpending(sigset_t *set);
下面是一个简单samplecode
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h> static int got_signal = ; static void hdl (int sig)
{
got_signal = ;
printf("signal handle hd1");
} int main (int argc, char *argv[])
{
sigset_t mask;
sigset_t orig_mask; if (signal(SIGTERM,hdl)) {
perror ("signal error");
return ;
} sigemptyset (&mask);
sigaddset (&mask, SIGTERM); if (sigprocmask(SIG_BLOCK, &mask, &orig_mask) < ) {
perror ("sigprocmask");
return ;
} sleep ();
if (sigpending(&mask) == ){
printf("Signal TERM is pending\n");
}
if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < ) {
perror ("sigprocmask");
return ;
} sleep (); if (got_signal)
puts ("Got signal"); return ;
}
一个函数的引入通常也引入了另一个问题,好像我的bug都是这样产生的,一个设计方案的导入通常会产生新的bug。现在有这样一个问题,我们希望变更一些信号处理函数,当前如果产生SIGA我们去做handA的操作,但是我们希望之后按照handB的操作去处理,最后又回到handA中又应该怎么处理呢?我们会使用以下的处理方式吗?
signal(SIGA, handA);
signal(SIGA, handB);
signal(SIGA, handA);
这种模式的缺点又在哪里呢?由于handA---->handB, handB--->handA的过程中不是原子操作,在handB--->handA的过程中产生一个SIGA信号会出现什么样的情况?这个信号岂不是丢失了。这里提供了两个信号处理函数无缝切换的函数。
int sigaction(int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);
关于信号这块剩余的最后一个函数就是 sigsuspend了。我们先来看看他出现的理由吧!
现在考虑一下的模型:
.
.
.
sigprocmask(SIG_SETMASK, &oldmask, NULL);
pause();
以上的模型中如果在sigprocmask和pause之间发生了该信号,会发生什么事情?还没有执行pause函数,进程 接受到该信号后也不会被唤醒。最后导致该信号被丢失。导致信号丢失的原因在于sigprocmask和pause不是原子操作,在sigprocmask和pause之间有一个时间段,从而导致了信号丢失的发生。解决这个问题之要将sigprocmask和pause合并成要给原子操作就可以,于是就有了如下函数:
int sigsuspend(const sigset_t *sigmask);
以上是对APUEsignal一章的学习总结,错误之处还望指出。
APUE学习之------------信号的更多相关文章
- APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause
转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int k ...
- APUE学习心得
APUE学习心得 Chapter 3 IO 3.2 文件描述符 文件描述符是一个非负整数.当打开 一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符.0 标准输入,1 标准输出, 2 标准错 ...
- Qt学习之信号与槽(一)
Qt学习之信号与槽(一) 目录 QT的信号与槽机制 在窗口的UI设计中操作添加信号和槽 QT的信号与槽机制 QT的两种机制 在Qt和PyQt中有两种通信机制: 低级事件处理机制(low-l ...
- APUE学习笔记3_文件IO
APUE学习笔记3_文件IO Unix中的文件IO函数主要包括以下几个:open().read().write().lseek().close()等.这类I/O函数也被称为不带缓冲的I/O,标准I/O ...
- APUE学习笔记——10.11~10.13 信号集、信号屏蔽字、未决信号
如有转载,请注明出处:Windeal专栏 首先简述下几个概念的关系: 我们通过信号集建立信号屏蔽字,使得信号发生阻塞,被阻塞的信号即未决信号. 信号集: 信号集:其实就是一系列的信号.用sigset_ ...
- APUE学习笔记——10信号——信号接口函数 signal 和 sigaction
signal函数 signal函数是早起Unix系统的信号接口,早期系统中提供不可靠的信号机制.在后来的分支中,部分系统使用原来的不可靠机制定义signal函数,如 Solaris 10 .而 ...
- APUE学习笔记——10 信号
信号的基本概念 信号是软件中断,信号提供了解决异步时间的方法. 每一中信号都有一个名字,信号名以SIG开头. 产生信号的几种方式 很多条件可以产生信号: 终端交互:用户 ...
- apue学习笔记(第十章 信号)
本章先对信号机制进行综述,并说明每种信号的一般用法. 信号概念 每个信号都有一个名字,这些名字都以3个字符SIG开头.在头文件<signal.h>中,信号名都被定义为正整形常量. 在某个信 ...
- APUE学习笔记——10.可靠信号与不可靠信号
首先说明:现在大部分Unix系系统如Linux都已经实现可靠信号. 1~31信号与SIGRTMIN-SIGRTMAX之间并不是可靠信号与不可靠信号的区别,在大多数系统下他们都是可靠信号. 只不过: 1 ...
随机推荐
- 在windows后台调用webservice
1.首先要创建个webservice,然后再webservice写一个方法如图 2.然后将WebService1.asmx 在浏览器中浏览会出现如图所示(该地址很重要,复制此地址在下边程序中要用到) ...
- rownum(转载)
对于 Oracle 的 rownum 问题,很多资料都说不支持>,>=,=,between...and,只能用以上符号(<.<=.!=),并非说用>,>=,=,be ...
- 实现单例模式C++版本
还是先看最简单的C++单例模式 class CSingleton { private: CSingleton(){} static CSingleton *pInstance; public: sta ...
- PhpStorm 10.0 激活方式
随着 JetBrains 新版本的发布,注册机已然不行了.然而,道高一尺,魔高一丈.IntelliJ IDEA开源社区 提供了如下通用激活方法:注册时选择License server填写http:// ...
- Arduino Micro USB库
USBCore.cpp #define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_co ...
- css 自适应布局阮一峰
转载一篇文章: 自适应网页设计(Responsive Web Design) 作者: 阮一峰 移动设备正超过桌面设备,成为访问互联网的最常见终端.于是,网页设计师不得不面对一个难题:如何才能在不同大小 ...
- Jsoup代码解读之四-parser
Jsoup代码解读之四-parser 作为Java世界最好的HTML 解析库,Jsoup的parser实现非常具有代表性.这部分也是Jsoup最复杂的部分,需要一些数据结构.状态机乃至编译器的知识.好 ...
- Java知识点复习
总结下java的知识点 final 关键字-方法:不能被子类重写(override)-变量:不能被修改-类:不可以被继承,派生子类 finally 关键字与try/catch语句配合使用,即使有异常抛 ...
- Oracle 11g RAC database on ASM, ACFS or OCFS2
I see a lot of questions on shared file systems that can be used when people move from single instan ...
- 成都Uber优步司机快速注册攻略(外地车牌也可加入,不用现场培训)
我加入Uber司机有一段时间了,有一些经验和感想分享给大家,让大家少走些弯路.目前加入优步不收取任何费用,不需要抢单,时间安排自由灵活,使用便捷,深受大众喜爱. 加入人民优步拼车条件:购买运行5年之内 ...