Linux 信 號 機 制

2021-07-29 21:25:11 字數 2358 閱讀 4476

前面介紹了訊號的基本概念,在這一節中,我們將介紹核心如何實現訊號機制。即核心如何向乙個程序傳送訊號、程序如何接收乙個訊號、程序怎樣控制自己對訊號的反應、核心在什麼時機處理和怎樣處理程序收到的訊號。還要介紹一下setjmp和longjmp在訊號中起到的作用。 

1、核心對訊號的基本處理方法

核心給乙個程序傳送軟中斷訊號的方法,是在程序所在的程序表項的訊號域設定對應於該訊號的位。這裡要補充的是,如果訊號傳送給乙個正在睡眠的程序,那麼要看 該程序進入睡眠的優先順序,如果程序睡眠在可被中斷的優先順序上,則喚醒程序;否則僅設定程序表中訊號域相應的位,而不喚醒程序。這一點比較重要,因為程序檢 查是否收到訊號的時機是:乙個程序在即將從核心態返回到使用者態時;或者,在乙個程序要進入或離開乙個適當的低排程優先順序睡眠狀態時。 

核心處理乙個程序收到的訊號的時機是在乙個程序從核心態返回使用者態時。所以,當乙個程序在核心態下執行時,軟中斷訊號並不立即起作用,要等到將返回使用者態時才處理。程序只有處理完訊號才會返回使用者態,程序在使用者態下不會有未處理完的訊號。 

內 核處理乙個程序收到的軟中斷訊號是在該程序的上下文中,因此,程序必須處於執行狀態。前面介紹概念的時候講過,處理訊號有三種型別:程序接收到訊號後退 出;程序忽略該訊號;程序收到訊號後執行使用者設定用系統呼叫signal的函式。當程序接收到乙個它忽略的訊號時,程序丟棄該訊號,就象沒有收到該訊號似 的繼續執行。如果程序收到乙個要捕捉的訊號,那麼程序從核心態返回使用者態時執行使用者定義的函式。而且執行使用者定義的函式的方法很巧妙,核心是在使用者棧上創 建乙個新的層,該層中將返回位址的值設定成使用者定義的處理函式的位址,這樣程序從核心返回彈出棧頂時就返回到使用者定義的函式處,從函式返回再彈出棧頂時, 才返回原先進入核心的地方。這樣做的原因是使用者定義的處理函式不能且不允許在核心態下執行(如果使用者定義的函式在核心態下執行的話,使用者就可以獲得任何權 限)。 

在訊號的處理方法中有幾點特別要引起注意:

第一,在一些系統中,當乙個程序處理完中斷訊號返回使用者態之前,核心清除使用者區中設 定的對該訊號的處理例程的位址,即下一次程序對該訊號的處理方法又改為預設值,除非在下一次訊號到來之前再次使用signal系統呼叫。這可能會使得程序 在呼叫signal之前又得到該訊號而導致退出。在bsd中,核心不再清除該位址。但不清除該位址可能使得程序因為過多過快的得到某個訊號而導致堆疊溢 出。為了避免出現上述情況。在bsd系統中,核心模擬了對硬體中斷的處理方法,即在處理某個中斷時,阻止接收新的該類中斷。 

第二個要 引起注意的是,如果要捕捉的訊號發生於程序正在乙個系統呼叫中時,並且該程序睡眠在可中斷的優先順序上,這時該訊號引起程序作一次longjmp,跳出睡眠 狀態,返回使用者態並執行訊號處理例程。當從訊號處理例程返回時,程序就象從系統呼叫返回一樣,但返回了乙個錯誤**,指出該次系統呼叫曾經被中斷。這要注 意的是,bsd系統中核心可以自動地重新開始系統呼叫。 

第三個要注意的地方:若程序睡眠在可中斷的優先順序上,則當它收到乙個要忽略的訊號時,該程序被喚醒,但不做longjmp,一般是繼續睡眠。但使用者感覺不到程序曾經被喚醒,而是象沒有發生過該訊號一樣。 

第 四個要注意的地方:核心對子程序終止(sigcld)訊號的處理方法與其他訊號有所區別。當程序檢查出收到了乙個子程序終止的訊號時,預設情況下,該程序 就象沒有收到該訊號似的,如果父程序執行了系統呼叫wait,程序將從系統呼叫wait中醒來並返回wait呼叫,執行一系列wait呼叫的後續操作(找 出僵死的子程序,釋放子程序的程序表項),然後從wait中返回。sigcld訊號的作用是喚醒乙個睡眠在可被中斷優先順序上的程序。如果該程序捕捉了這個 訊號,就象普通訊號處理一樣轉到處理例程。如果程序忽略該訊號,那麼系統呼叫wait的動作就有所不同,因為sigcld的作用僅僅是喚醒乙個睡眠在可被 中斷優先順序上的程序,那麼執行wait呼叫的父程序被喚醒繼續執行wait呼叫的後續操作,然後等待其他的子程序。 

如果乙個程序呼叫signal系統呼叫,並設定了sigcld的處理方法,並且該程序有子程序處於僵死狀態,則核心將向該程序發乙個sigcld訊號。 

2、setjmp和longjmp的作用

前面在介紹訊號處理機制時,多次提到了setjmp和longjmp,但沒有仔細說明它們的作用和實現方法。這裡就此作乙個簡單的介紹。 

在 介紹訊號的時候,我們看到多個地方要求程序在檢查收到訊號後,從原來的系統呼叫中直接返回,而不是等到該呼叫完成。這種程序突然改變其上下文的情況,就是 使用setjmp和longjmp的結果。setjmp將儲存的上下文存入使用者區,並繼續在舊的上下文中執行。這就是說,程序執行乙個系統呼叫,當因為資 源或其他原因要去睡眠時,核心為程序作了一次setjmp,如果在睡眠中被訊號喚醒,程序不能再進入睡眠時,核心為程序呼叫longjmp,該操作是核心 為程序將原先setjmp呼叫儲存在程序使用者區的上下文恢復成現在的上下文,這樣就使得程序可以恢復等待資源前的狀態,而且核心為setjmp返回1,使 得程序知道該次系統呼叫失敗。這就是它們的作用。

linux 訊號機制

本文旨在弄懂linux中的訊號工作原理 kill l 命令可以檢視linux下所有訊號 2.1 使用者在終端按下某些鍵時,終端驅動程式會傳送訊號給前台程序 例如ctrl c產生sigint訊號,ctrl 產生sigquit訊號,ctrl z產生sigtstp訊號 2.2 硬體異常產生訊號,這些條件由...

LINUX訊號機制

在電腦科學中,訊號是unix 類unix以及其他posix相容的作業系統中程序間通訊的一種有限制的方式。它是一種非同步的通知機制,用來提醒程序乙個事件已經發生。當乙個訊號傳送給乙個程序,作業系統中斷了程序正常的控制流程,此時,任何非原子操作都將被中斷。如果程序定義了訊號的處理函式,那麼它將被執行,否...

Linux 訊號機制 (二)

推薦一篇好文章 文章二 程序即將從核心態返回使用者態的時候,才會處理訊號 執行訊號處理函式 使用者程序什麼時候從核心態返回使用者態呢?系統呼叫 使用者主動進入核心 中斷 使用者程序被動進入核心 被排程執行 使用者從等待執行,變為正在執行 訊號處理函式時使用者態函式,但是需要在核心態的條件下執行。所以...