linux 2.4内核之信号(一)

2020-05-21 00:00:00 用户 进程 接收 信号 位图

linux 2.4内核之信号(一)

这两天看信号,略有所感.记下以示.

限于规模.只是略讲以及自己困惑过的地方.由于描述能力和理解力

错误的地方还请多谅解和指正

begin:

1.信号的许多基础问题我就不说了(当然是我认为的).这里主要讲下几个比较搞的概念

信号屏蔽: 主要区分好block和sa_mask就好,信号有两个地方屏蔽,是进程的task_struct中有一个

block,这是一直起作用的.还有就是设置信号处理程序时的sigaction结构的sa_mask.kill,stop信号不允许

被屏蔽.当然也不能设置处理函数. 在信号发送时,要将一个接收位图相关的位置1,并将信号挂入一个队列.

如果接收进程对应该信号没有被block,则唤醒接收进程

2. 信号接收位图:

当接收到信号后,要将对应的信号位图置1.被处理后再置回0,但由于由于在接收信号和处理信号之间还可能有

信号被接收,即存在时间窗口,信号可能被合并.所以引入了一个struct sigqueue.当发送信号时,就将

pending对应的位图置1.并加入sigqueue.这样才能保证记录信号的次数.但是对于以前老的机制(信号值小于

SIGRTMIN的),内核只将其抽取构造出相应结构,挂入sigqueue一次.所以信号值小于SIGRTMIN的信号,在处理

时,并不能记录在时间窗口中发生的次数,还是会合并掉

3. do_signal()

进程检测信号存在的时机.当(1)从系统调用返回,中断异常处理返回时,会检测信号task struct ->

sigpending.(2)当进程被唤醒时(必定是在系统调用中),如果发现有信号等待就提前从系统调用中返回.

这里主要讲一下是如何处理接收位图的.因为一开始这里没弄清楚(主要是忽略了dequeue_signal的代码,因为

情景分析里面没讲).具体实现就是在dequeue_signal()中,这个函数先参照block位图(看dequeue_signal

(t->blocked, &info);传了blocked参数),再根据进程的接收位图找到要处理的信号(即设置了位1)然后使其

脱队,再进行处理(实际上这个时候还没处理,还在系统空间为返回做准备,没切换到用户空间.在do_signal()

返回后才切换.).如果没有设置SA_NODEFER属性,则当前要处理的信号被自动屏蔽(是block).即通过

sigaddset(t->blocked,sig);实现,具体在内核和用户空间切换的代码还没看.反正切换到用户空间处理后再

通过一个系统调用回到系统空间.如果还有信号则继续处理.(不要问为什么不能一次性处理完,要在系统空间和

用户换来换去.记住处理程序在用户空间.)

4.后注意sigorsets(t->blocked,t->blocked,&ka->sa.sa_mask); 从用户的信号屏蔽码刷新阻塞信

号集.找到了这个.相信可以区分一开始讲的进程的block还有sigaction结构的sa_mask(它其实也靠进程的

block位图实现屏蔽.) 还有一个接收位图了吧..虽然它们的类型都是sigset_t;

补充一下,使信号脱队时,只有判断所有同种信号都脱队完时,才能清接收位图的标志位。

这在collect_signal()函数中可以找到具体代码

文章来源CU社区:linux 2.4内核之信号(一)

相关文章