generate and deliver signal


在linux里,generate signal是指在接受信号的进程结构中插入信号的相关结构(在进程的结构中有两个跟信号相关的队列,一个是pending field里的信号队列,一个是signal field里的信号队列
其中pending指向的是进程的私有信号,而signal里的是进程所在进程组的共有信号)。这个结构名为struct sigqueue.需要补充说明的是,如果信号是被进程忽略的,忽略一个信号需要满足的3个条件是:
1.The process is not being traced (PT_PTRACED flag in t->ptrace clear).

2.The signal is not blocked (sigismember(&t->blocked, sig) returns 0).

3.The signal is either explicitly ignored (the sa_handler field of t->sighand->action[sig-1] is equal to SIG_IGN) or implicitly ignored (the sa_handler
field is equal to SIG_DFL and the signal is SIGCONT, SIGCHLD, SIGWINCH, or SIGURG).
那么是不会创建信号的结构的。如果因为某种原因比如内存空间不够,信号结构无法创建,但是仍然会更新sigpending结构里的signal field。这样是为了保证就算内存不够,也使得管理员可以杀死恶意的进程
,通过发送kill信号给它。
deliver signal是指linux让进程开始处理pending的信号。
在generate signal的最后,kernel会选择要进行信号处理的进程,将进程的状态设为TASK_RUNNING,如果进程本来就在运行,那么将会对进程进行reschedule,这样使得能尽快对进程信号进行相应。
因为只有从内核态返回用户态时,才会对进程的信号bit进行检查。如果信号是发给一个进程组的,那么kernel将会选择一个满足下面条件的进程来处理信号。
kernel在处理完中断和异常后,会检查即将运行的进程的信号bit,如果进程有信号要处理,会对进程的信号队列的信号进行处理。首先处理的是进程的私有信号队列,然后是进程的共有信号。具体处理的函数
叫do_signal(),函数里有一个loop,将会使得所有的信号都得到处理,但是有一点要注意的是如果进程为信号,设置了自己的处理函数,那么会导致退出do_signal()函数,代码示例:
handle_signal(signr, &info, &ka, oldset, regs);
    if (ka->sa.sa_flags & SA_ONESHOT)
        ka->sa.sa_handler = SIG_DFL;
    return 1;
handle_signal是用来调用进程自己定义的信号处理函数。
所以Notice how do_signal( ) returns after having handled a single signal. Other pending signals won't be considered until the next invocation of
do_signal( ). This approach ensures that real-time signals will be dealt with in the proper order.
由于信号的到来会唤醒被阻塞的进程,有时进程的阻塞是因为系统调用的资源无法满足,在这种情况下,由于信号唤醒了进程,而信号处理完后,进程将继续运行(位于系统调用后的代码),使得进程之前
执行的系统调用没有运行完,这显然是不允许的。所以kernel在deliver 一个信号的时候会检查进程之前是否进行了系统调用,如果是的话,系统将会采用3种处理方法:
Terminate

The system call will not be automatically reexecuted; the process will resume its execution in User Mode at the instruction following the int $0x80 or sysenter one and the eax register will contain the -EINTR value.

 

Reexecute

The kernel forces the User Mode process to reload the eax register with the system call number and to reexecute the int $0x80 or sysenter instruction; the process is not aware of the reexecution and the error code is not passed to it.

 

Depends

The system call is reexecuted only if the SA_RESTART flag of the delivered signal is set; otherwise, the system call terminates with a -EINTR error code.

这里还有一点要提醒的是,reexecute有时不能只是将前面的系统调用重新调用一次,参数用前面的。比如如果之前调用的系统调用是sleep(3),那么由于时间可能已经过了2,那么reexecute的时候,
就应该这样调用sleep(1)。
2009/02/17 二

 

 

 

 

 

 


 


 


 

 


 

 

 

 

 


 


 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值