在linux内核2.6.11中,sys_sigsuspend怎么可能是原子的?

在linux内核2.6.11中,sys_sigsuspend怎么可能是原子的?,linux,kernel,Linux,Kernel,我正在读linux 2.6.11 sys_SIGSSUSPEND的实现如下 34 /* 35 * Atomically swap in the new signal mask, and wait for a signal. 36 */ 37 asmlinkage int 38 sys_sigsuspend(int history0, int history1, old_sigset_t mask) 39 { 40 struct pt_regs * regs =

我正在读linux 2.6.11 sys_SIGSSUSPEND的实现如下

 34 /*
 35  * Atomically swap in the new signal mask, and wait for a signal.
 36  */
 37 asmlinkage int
 38 sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 39 {
 40         struct pt_regs * regs = (struct pt_regs *) &history0;
 41         sigset_t saveset;
 42 
 43         mask &= _BLOCKABLE;
 44         spin_lock_irq(&current->sighand->siglock);
 45         saveset = current->blocked;
 46         siginitset(&current->blocked, mask);
 47         recalc_sigpending();
 48         spin_unlock_irq(&current->sighand->siglock);
 49 
 50         regs->eax = -EINTR;
 51         while (1) {
 52                 current->state = TASK_INTERRUPTIBLE;
 53                 schedule();
 54                 if (do_signal(regs, &saveset))
 55                         return -EINTR;
 56         }
 57 }
在ULK3中,作者说

sigssuspend()系统调用不允许在取消阻塞之后和schedule()调用之前发送信号,因为其他进程无法在该时间间隔内获取CPU

在spin_unlock_irq和schedule之间,系统调用可以被中断和抢占,因此另一个进程可以有足够的时间向进程发送未被阻塞的信号

但在这种情况下,信号将丢失,因为信号交付后的处理进度

这就是为什么SIGSSUSPEND应该是原子的,但它不符合它的实现

SIGSSUSPEND实现是正确的,但ULK中的解释似乎有误导性

当进程执行内核代码时,该执行永远不会被用户的信号中断。相反,这些信号在当前任务结构中积累。在进程离开内核代码并返回给用户代码的那一刻,所有累积(且未阻塞)的信号都被触发

schedule()内核的函数检查是否积累了一些信号。如果是,并且
current->state
是任务可中断的,则schedule()返回。因此,在调用
schedule()
之前收集的所有信号都不会丢失


SIGSSUSPEND()系统调用的原子性意味着,如果发出了被调用暂时解除阻塞的信号,调用将保证看到这些信号并返回。这种原子性只需将解锁和检查信号放在同一个内核函数中即可实现。

u'r right。我又读了一遍。我误解了当从中断返回内核路径时(在嵌套内核路径的情况下),内核将处理挂起的信号。实际上,只有(在)返回到用户空间之前,内核才会处理挂起的信号。谢谢