信号

一个典型的信号处理与响应

程序中的信号处理过程

摘要

1.信号基本概念
2.信号产生的一般方式
3.信号递达盒阻塞的概念和原理
4.信号捕捉方式
5.可重入函数概念
6.竞态条件的情景和处理方式
7.SIGCHILD信号,编写信号处理函数的一般机制

信号的基本概念

一个熟悉场景

1用户输入命令,在shell下启动一个进程
2用户按下Ctrl-C,产生一个硬件中断
3如果CPU当前正在执行这个程序的代码,则用户空间代码暂停执行,CPU从用户态切换到内核态处理硬件中断
4终端驱动程序将Ctrl-C解释成一个SINGINT信号,记录在PCB中(进程接受信号)
5当某个时刻要从内核返回进程用户空间代码运行之前,首先处理PCB中的信号,发现有一个SIGINT信号待处理,其默认动作为终止进程,所以直接终止进程而不返回其用户空间继续执行

注:Ctrl-C信号只发送给前台进程,不能发送给后台进程

linux系统定义的信号列表
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX

注:每个信号都有编号和宏定义名称,在文件signal.h中
每个信号的默认处理动作在signal(7)中.    man 7 signal可以查看

信号产生的主要条件:
1用户在终端下按键Ctrl-C SIGINT   Ctrl-\  SIGQUIT  Ctrl-Z SIGTSP
2硬件异常产生信号  eg    /0  产生SIGFPE  非法地址访问产生SIGSEGV
3一个进程调用kill(2)函数发送信号给另一个进程

信号处理动作:
1忽略信号
2执行默认处理动作
3提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数(捕捉)

产生信号

A通过终端产生信号
B通过系统调用向进程发送信号 raise函数可以给当前进程发送指定的信号(自己给自己发送)
int kill(pid_t pid, int signo);
int raise(int signo);
abort 函数使当前进程接收到信号而异常终止
C由软件条件产生信号
unsigned int alarm(unsigned int seconds);

阻塞信号

A信号在内核中的表示

实际执行信号的处理动作称为信号递达
信号从产生到递达之间的状态称为信号未决

信号在内核中的状态

注:每个信号都有两个标志位表示阻塞(block)和未决(pending),还有一个函数指针表示处理东西.
信号产生时,内核在进程控制块中设置未决状态,直到信号递达才清除该标志

常规信号产生多次只记录一次,而实时信号抵达之前产生多次放在队列中
阻塞信号集也叫当前进程的信号屏蔽字(Signal Mask)

B信号集操作函数

int sigemptyset(sigset_t * set);
int sigfillset(sigset_t* set);
int sigaddset(sigset_t* set,int signo);
int sigdelset(sigset_t* set,int signo);
int sigismember(const sigset_t * set,int signo);

C.sigprocmask

调用函数sigprocmask可以读取或者更改进程的信号屏蔽字(阻塞信号集).
int sigprocmask(int how,const sigset_t * set,sigset_t *oset);
如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达

D.sigpending

int sigpending(sigset_t * set);
读取当前进程的未决信号集,通过set参数传出.

捕捉信号

A内核实现信号捕捉
1用户注册信号处理函数
2当前main发生中断或者异常切换到内核态
3在中断处理完毕之后返回用户之前检查是否有信号递达
4内核决定返回用户态后是不是恢复main上下文执行,而是执行handler函数
注:main和handler函数使用不同的堆栈空间,他们之间不存在调用和被调用的关系,是两个独立的控制流程
5handler函数返回后自动执行特殊系统调用sigreturn再次返回内核态
6如果没有新的信号递达,这次再返回用户态恢复main函数上下文继续执行

B.sigaction

int sigaction(int signo, const struct sigaction* act,struct sigaction* oact);
该函数可以读取和修改与指定信号相关联的处理动作(类似C++handler,修改同时返回old handler)

C.pause

int pause(void)
使得调用进程挂起等待信号递达.

D可重入函数
当一个函数被不同的控制流程调用,有可能第一次调用还没有返回时,再次进入该函数,者称为重入.
当函数因为重入可能造成错乱时,称为不可重入函数.否则称为可重入函数

不可重入规则:
调用了malloc或free,因为malloc也是全局链表管理堆的
调用了标准IO哭喊树,标准IO库的很多实现都以不可重入的方式使用全局数据结构

E.sig_atomic_t类型与volatile限定符

对于程序中存在多个执行流程访问同一变量的情况,volatile限定符是有必要的
此外,虽然程序只有单一的执行流程,但是变量属于以下情况,也需要volatile:
1变量在内存单元的数据不需要写操作就可以自己发生改变.每次读取的值都可能不一样

竞态条件与sigsuspend函数

eg当前进程设置闹钟(闹钟的计时是为当前进程做的),但是在当前进程等待过程中,优先级更高的进程获取执行权限,导致当前进程被挂起.而在闹钟结束之时进程仍然没有获取执行权限.那么就会导致程序出错.这就叫做静态条件

....

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容