2015-04-24 21 views
0

我讀的Linux 2.6.11 sys_sigsuspend的實現是以下sys_sigsuspend在Linux kernel 2.6.11中怎麼可能是原子的?

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作者說

的sigsuspend()系統調用不允許信號發送解除阻塞之後和schedule()調用之前,因爲其他進程在該時間間隔內無法獲取CPU。

之間spin_unlock_irq時間表系統調用可以被中斷並搶佔,因此其他過程可以有足夠的時間來發送該沒有被阻塞的過程

但是,在這種情況下的信號,信號將會丟失,因爲信號發送後的處理時間表。

這就是爲什麼sigsuspend應該是原子性的,但它不符合其實施。

回答

0

sigsuspend實現是正確的,但在ULK中的解釋似乎是誤導。

當進程執行內核代碼時,執行不會被用戶的信號中斷。相反,這些信號在目前的任務結構內部累積。當進程離開內核代碼並返回給用戶時,所有累積(而不是阻塞)的信號被觸發。

schedule()內核的功能檢查是否有一些信號被累加。如果是,則current->state爲TASK_INTERRUPTIBLE,計劃()返回。所以在schedule()呼叫之前收集的所有信號都不會丟失。

sigsuspend的原子性()系統調用意味着,如果信號,臨時暢通由呼叫,發射,則該呼叫將garantee看到它們並返回。這種原子性可以通過在相同的內核函數中放置解鎖和檢查信號來實現。

+0

u'r right。我又讀過了entry.S。我誤解了,當從中斷返回到內核路徑時(在嵌套內核路徑的情況下),內核將處理待定信號。實際上只有(之前)返回到用戶空間,內核將處理未決信號。謝謝 – gankme