一步一步学Linux C:sigsuspend 执行过程分析(2)

结果:

$a.out   in critical region: SIGINT   ^C   in sig_int: SIGINT   after return from sigsuspend: SIGINT  

如果按照sig_handler先返回,那么SIGINT是不该被打印出来的,因为那时屏蔽字还没有恢复,所有信号都是不阻塞的。那么是Stevens说错了么?当然没有,只是Stevens没有说请在sigsuspend的原子操作中到底做了什么?
sigsuspend的整个原子操作过程为:
(1) 设置新的mask阻塞当前进程;
(2) 收到信号,恢复原先mask;
(3) 调用该进程设置的信号处理函数;
(4) 待信号处理函数返回后,sigsuspend返回。
大致就是上面这个过程,噢,原来signal handler是原子操作的一部分,而且是在恢复屏蔽字后执行的,所以上面的例子是没有问题的,Stevens说的也没错。由于Linux和Unix的千丝万缕的联系,所以在两个平台上绝大部分的系统调用的语义是一致的。上面的sigsuspend的原子操作也是从《深入理解Linux内核》一书中揣度出来的。书中的描述如下:

/*The sigsuspend( ) system call puts the process in the TASK_INTERRUPTIBLE state, after having blocked the standard signals specified   by a bit mask array to which the mask parameter points. The process will wake up only when a nonignored, nonblocked signal is sent    to it. The corresponding sys_sigsuspend( ) service routine executes these statements:  */      mask &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP));   spin_lock_irq(¤t->sigmask_lock);   saveset = current->blocked;   siginitset(¤t->blocked, mask);   recalc_sigpending(current);   spin_unlock_irq(¤t->sigmask_lock);   regs->eax = -EINTR;   while (1) {       current->state = TASK_INTERRUPTIBLE;       schedule(  );       if (do_signal(regs, &saveset))           return -EINTR;   }   

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wywwjy.html