Linux訊號處理

來源:互聯網
上載者:User

標籤:kernel   核心   signal   訊號處理   

由於在下能力相當有限,有不當之處,還望大家批評指正^_^


一、 訊號概念


  • 訊號(signal)是非強制中斷。
  • 訊號提供了一種處理非同步事件的方式。
  • 當各種各樣的事件發生時,程式相應的會收到各種各樣的訊號。
  • 對於大部分訊號,程式可以自行決定如何處理他們。

程式在什麼情況下會收到訊號,下面是一些例子
執行某條指令,產生了異常
   (例如, 訪存指令訪問無效記憶體時收到SIGSEGV訊號,執行非法指令收到SIGILL訊號)
執行某些不合適的操作
  (例如,寫破列的管道收到SIGPIPE訊號,背景程式向控制台列印資訊收到SIGTTOU訊號)
發生了一些與當前程式有關的事情
  (例如,子進程退出後父進程收到SIGCHLD訊號,定時器時間到了收到SIGALRM訊號)
程式之間相互發送訊號
  (例如, 程式之間通過訊號進行協作)

通過man 7 signal命令可以查看Linux下的訊號說明。下面列出了此命令輸出的一些訊號,包括訊號的編號,預設處理方式。注意,同一訊號,在不同CPU架構下的編號可能不一樣。例如,像SIGUSR1, SIGCONT等。





二、 訊號處理
對於一個訊號如何處理,程式有如下3種選擇
  • 忽略 
  • 捕獲並處理 
  • 讓系統按預設處理
注意:   SIGKILL與SIGSTOP訊號,即無法被忽略,也無法被捕獲。

Linux訊號處理,有兩種機制, 一種是傳統的,一種是現代的。
總得來說,傳統的訊號處理機制有多種缺陷,因此還是不用為好。另外,關於程式處理訊號的具體方法,本文就不介紹了。《UNIX環境進階編程》對這些知識說得已經非常好了。
本文著重講講訊號處理機制中的某些特殊之處。

三、 多線程程式中的訊號處理
程式中對於某個訊號如何處理的設定,對所有線程都是相同的。換句話說,對任一訊號設定的處理方式,以及相應的訊號處理函數,對於所有線程都是共用的。
每個經程,通過pthread_sigmask設定自己要阻塞的訊號。
問題是,這樣的話,訊號來了,具體由哪個線程誰處理呢???
這要分幾種情況來討論:
1. 外界向本進程發送的信號(通過sys_kill系統調用)答案是,如果沒有特殊情況,都是主線程處理。如果主線程不能處理,則選出一個線程來處理。具體如何?的,下面貼出核心中的相關代碼
/* * Now find a thread we can wake up to take the signal off the queue. * * If the main thread wants the signal, it gets first crack. * Probably the least surprising to the average bear. */if (wants_signal(sig, p))t = p;else if (!group || thread_group_empty(p))/* * There is just one thread and it does not need to be woken. * It will dequeue unblocked signals before it runs again. */return;else {/* * Otherwise try to find a suitable thread. */t = signal->curr_target;while (!wants_signal(sig, t)) {t = next_thread(t);if (t == signal->curr_target)/* * No thread needs to be woken. * Any eligible threads will see * the signal in the queue soon. */return;}signal->curr_target = t;}




2. 直接向某線程發送的訊號(通過sys_tkill系統調用)答案是,只會由此線程自己處理。
3.  線程執行相關指令產生的訊號某線程執行指令,導致產生了SIGSEGV或SIGILL,只會由產生此訊號的線程自己處理。


最後,如何讓線程專心做事,不被進程收到的訊號打斷呢。
同時,訊號又能夠得到妥善的處理。一種解決方案是:所有線程均阻塞所有process-directed訊號,由一個線程輪詢接收處理這些訊號。


四、核心中的相關實現(引用核心版本2.6.32)1. 核心何時處理訊號任務進入核心態後,在即將返回使用者態之前,核心檢查當前任務是否有訊號需要處理。有的話,就處理訊號。
任務一般會因為中斷、系統調用、指令異常這幾個原因,進入核心態。但不管是哪一種,在返回使用者態之前,核心都會做訊號方面的檢查與處理。這個流程是一樣的。
以i386為例,其代碼在如下檔案中。
arch\x86\kernel\entry_32.S


2. 訊號處理代碼簡析
a). 訊號處理總入口
static void do_signal(struct pt_regs *regs)
他由do_notify_resume調用


b). get_signal_to_deliver中處理被忽略的訊號,以及按預設處理的訊號


c). handle_signal中處理使用者設定了要捕獲處理的訊號

3. 核心如何重啟被訊號打斷的系統調用 


以ioctl為例。在x86_64下,其系統調用號為16。
見arch\x86\include\asm\unistd_64.h


ioctl的C庫函數彙編代碼如下:
000000000040af30 <__ioctl>:
40af30: b8 10 00 00 00      mov    $0x10,%eax
40af35: 0f 05               syscall 
40af37: 48 3d 01 f0 ff ff   cmp    $0xfffffffffffff001,%rax
40af3d: 0f 83 ad 23 00 00   jae    40d2f0 <__syscall_error>
40af43: c3                  retq   
40af44: 90                  nop    
40af45: 90                  nop 




handle_signal中的代碼片斷如下:
case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->ax = -EINTR;
break;
}
/* fallthrough */
case -ERESTARTNOINTR:
regs->ax = regs->orig_ax;
regs->ip -= 2;  //等於回到__ioctl中調用syscall之前的地方了
break;


4. 使用者態訊號處理函數的執行
當線程要從核心態回到使用者態時,如果有訊號要處理,那麼就不是回到使用者態原先因為進核心而被中斷的地方執行了。而是回到使用者佈建的訊號處理函數的地址處開始執行,就好像線程當初進入核心前正要執行訊號處理函數一樣。
以x86_32,傳統訊號處理方式為例。
代碼在ia32_setup_frame中
核心將使用者態程式現場修改為,回到使用者態正好要執行的下一條指令,就是使用者態訊號處理函數的第一條指令。這樣,回到使用者態,就從使用者態訊號處理函數第一條指令開始執行了。
5. 使用者態訊號處理函數的返回
以x86_32,傳統訊號處理方式為例。
核心在ia32_setup_frame中為返回做好了準備

使用者態訊號處理函數的棧幀中,返回地址被核心賦了相應的值。即使用者態訊號處理函數在返回時,會返回到核心事先安排好的地方繼續執行。其實就是調用__NR_ia32_sigreturn,對應sys_sigreturn。
sys_sigreturn中就作了現場環境的恢複。
主要是restore_sigcontext這個函數。
他從棧裡面取出現場環境資料,進行恢複。
這些棧裡面的資料,則是前面在ia32_setup_frame 處理中,通過調用函數ia32_setup_sigcontext進行儲存的。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Linux訊號處理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.