linux sigsuspend 函數的作用

來源:互聯網
上載者:User

linux sigsuspend 函數的作用
2010-07-08 19:36:30

分類: LINUX

Unix提供了等待訊號的系統調用,sigsuspend就是其中一個,在CU(www.chinaunix.net)上曾經討論過一個關於該系統調用的問題,這裡也做一下解疑。

CU 網友討論的問題的核心就是到底sigsuspend先返回還是signal handler先返回。這個問題Stevens在《Unix環境進階編程》一書中是如是回答的“If a signal is caught and if the signal handler returns, then sigsuspend returns and the signal mask of the process is set to its value before the call to sigsuspend.”,由於sigsuspend是原子操作,所以這句給人的感覺就是先調用signal
handler先返回,然後sigsuspend再返回。但其第一個例子這麼講又說不通,看下面的代碼:
CU上討論該問題起於中的該例子:
int main(void) {
   sigset_t   newmask, oldmask, zeromask;

   if (signal(SIGINT, sig_int) == SIG_ERR)
      err_sys("signal(SIGINT) error");

   sigemptyset(&zeromask);

   sigemptyset(&newmask);
   sigaddset(&newmask, SIGINT);
   /* block SIGINT and save current signal mask */
   if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
      err_sys("SIG_BLOCK error");

   /* critical region of code */
   pr_mask("in critical region: ");

   /* allow all signals and pause */
   if (sigsuspend(&zeromask) != -1)
      err_sys("sigsuspend error");
   pr_mask("after return from sigsuspend: ");

   /* reset signal mask which unblocks SIGINT */
   if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
      err_sys("SIG_SETMASK error");

   /* and continue processing ... */
   exit(0);
}

static void sig_int(int signo) {
   pr_mask("\nin sig_int: ");
   return;
}
 
結果:
$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;
}
而最後的do_signal函數調用則是負責調用User Signal Handler的傢伙。我想到這CU上的那個問題該被解疑清楚了吧。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.