一、产生信号的三种方式:

1.由键盘(终端按键)产生,比如在shell下启动一个前台进程(控制台下的进程),按Ctrl^C(只能发给前台进程)会产生一个硬件中断,若CPU正在执行此进程代码,则该进程用户空间代码暂停执行,CPU从用户态切换到内核态处理中断,如果不是自定义信号处理函数,一般默认的处理动作为终止进程,所以在内核态直接终止进程而不返回用户区。

2.由系统函数发送信号,可用kill命令给某个指定进程发送信号,它是调用kill函数实现的。

模型:kill -发送几号信号 给哪个进程 例:kill -2 2978给进程号为2978进程发2号信号

raise函数可以自己给自己发送信号  int raise(int sig)

abort函数使当前进程接受到SIGABRT信号而异常中止 void abort(void)

3.由软件条件产生

alarm函数原型:unsigned int alarm(unsigned int seconds)

可调用alarm函数设定一个闹钟,经过secs秒后给当前进程发SIGALRM信号,该信号默认处理动作为终止进程。如下图:

wKioL1crEgnT4tCrAABDqgw0XSk572.png

wKiom1crETPQ_6veAAAhm8EEsP4123.png


二、阻塞信号

首先看看信号在内核中的表示示意图

task_struct为LINUX下的PCB(描述进程的信息),block表决定阻塞哪一个信号,pending表用来记录当前信号是否产生,handler表执行处理信号动作。每个信号只有一个bit的未决标志,即非0即1

wKiom1crEbfBnHr8AABLfz2qe3I242.png

解释几个概念:

1.信号递达:指的是实际处理信号的三种动作:(1).默认处理动作 (2).忽略该信号 (3).自定义信号处理即信号的捕捉。(一般不是立即处理一个信号,而是在合适的时机处理,只有9号信号是立即处理)

2.信号未决:从信号产生到递达之间的状态。

进程可以阻塞一个信号,当该阻塞信号产生时一直处于未决状态,直到解除阻塞信号才能递达。普通信号在递达之前若产生多次只计一次,一个信号若未产生也可以被阻塞掉

sigset_t 信号集可以表示每个信号有效或无效的状态

有关信号集的操作函数:

int sigemptyset(sigset_t *sig);//初始化sig指向的信号集

int sigaddset(sigset_t *sig,int sigo)//在该信号集中添加某个有效信号

bool sigismember(const sigset_t *sig,int sigo)//判断某个信号是否处于当前信号集中

int sigprocmask(int how,const sigset_t* sig,sigset_t* osig)//读取或更改进程的信号屏蔽字即修改block表.当对信号屏蔽字进行修改时,先保存原来信号屏蔽字保存起来。

int sigpending(sigset_t *sig)//获取当前进程的未决(pending)信号集

如下图所示例:将2号信号添加到当前信号集中,阻塞该信号,然后不断获取当前进程未决信号集,到达一定时间后解除对该信号的阻塞。信号递达后执行默认信号处理动作

wKiom1crGKCiKtEFAABgyDf1n8U881.png

wKiom1crGKHRG-HNAAAwBRVLxyQ112.png

wKiom1crGvTxwVO2AAA1XbgZZBo920.png

wKiom1crGvThdcJgAAAsgJ-NYI4237.png


查看某信号是否在该信号集中消失,可自定义动作捕捉某信号

内核如何实现信号的捕捉

wKiom1crHmqDECmxAAFtrlUZD9U373.png

调用函数signal(int sigo,void* handler)

wKiom1crG_bQXZuuAABVkUAkGC0788.png

wKiom1crHJKh4DgrAAArM54d9cc093.png

也可以使用sigaction函数修改handler表

注册一个信号处理函数

函数原型:int sigaction(int sigo,const struct sigaction* act,struct sigaction* oact)//对哪个信号进行设置,将要设置进去的结构体进行初始化,保存原来的信号

wKiom1crHcKRY8WQAABTO7-SwkQ538.png

wKiom1crHcLwaOH5AAAjiQJoAlY247.png



编写my_sleep函数

pause函数使调用进程一直挂起直到由信号递达,虽然handler自定义函数未执行任何动作,但必须使用该自定义处理信号函数,若信号的处理动作是终止,则终止该进程,pause函数没有机会返回,若为忽略动作,则pause函数将会忽略该信号一直挂起,但处理动作为捕捉,则调用处理函数后pause返回-1.

wKiom1crIs-y6CkHAAAf1vyLEIY617.png

wKioL1crIPHgEoBDAABfnbfQ7OI876.pngwKiom1crIJPQhPNiAAArY5wQtMg331.png

文件依赖关系另一写法

wKiom1crIWPAPJlgAAAjtgtXA-g669.png

总结:通过该模块了解信号的几种产生方式,以及信号在内核中的存储和如何修改某张表上的信号信息。