linux 2.4内核之信号(一)
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内核之信号(一)
相关文章