程序上下文和中斷上下文 原子上下文的區別

2021-06-21 05:33:26 字數 2860 閱讀 3214

核心空間和使用者空間是現代作業系統的兩種工作模式,核心模組執行在核心空間,而 使用者態應用程式執行在使用者空間。它們代表不同的級別,而對系統資源具有不同的訪問許可權。核心模組執行在最高端別(核心態),這個級下所有的操作都受系統信 任,而應用程式執行在較低級別(使用者態)。在這個級別,處理器控制著對硬體的直接訪問以及對記憶體的非授權訪問。核心態和使用者態有自己的記憶體對映,即自己的 位址空間。

系統的兩種不同於行狀態,才有了上下文的概念。使用者空間的應用程式,如果想請求系統服務,比如操作某個物理裝置,對映裝置的位址到使用者空間,必須通過系統呼叫來實現。(系統呼叫是作業系統提供給使用者空間的介面函式)。如下圖所示:

通過系統呼叫,使用者空間的應用程式就會進入核心空間,由核心代表該程序執行於核心空間,這就涉及到上下文的切換,使用者空間和核心空間具有不同的 位址對映,通用或專用的暫存器組,而使用者空間的程序要傳遞很多變數、引數給核心,核心也要儲存使用者程序的一些暫存器、變數等,以便系統呼叫結束後回到使用者 空間繼續執行,所謂的程序上下文,就是乙個程序在執行的時候,cpu的所有暫存器中的值、程序的狀態以及堆疊上的內容,當核心需要切換到另乙個程序時,它 需要儲存當前程序的所有狀態,即儲存當前程序的程序上下文,以便再次執行該程序時,能夠恢復切換時的狀態,繼續執行。

同理,硬體通過觸發訊號,向cpu傳送中斷訊號,導致核心呼叫中斷處理程式,進入核心空間。這個過程中,硬體的一些變數和引數也要傳遞給核心, 核心通過這些引數進行中斷處理,中斷上下文就可以理解為硬體傳遞過來的這些引數和核心需要儲存的一些環境,主要是被中斷的程序的環境。

linux核心工作在程序上下文或者中斷上下文。提供系統呼叫服務的核心**代表發起系統呼叫的應用程式執行在程序上下文;另一方面,中斷處理程式,非同步執行在中斷上下文。中斷上下文和特定程序無關。

執行在程序上下文的核心**是可以被搶占的(linux2.6支援搶占)。但是乙個中斷上下文,通常都會始終占有cpu(當然中斷可以巢狀,但我們一般不這樣做),不可以被打斷。正因為如此,執行在中斷上下文的**就要受一些限制,不能做下面的事情:

1. 睡眠或者放棄cpu。

由於中斷上下文不屬於任何程序,它與current沒有任何關係(儘管此時current指向被中斷的程序),所以中斷上下文一旦睡眠或者放棄cpu,將無法被喚醒。所以也叫原子上下文(atomic context)。

2. 嘗試獲得訊號量

為了保護中斷控制代碼臨界區資源,不能使用mutexes。如果獲得不到訊號量,**就會睡眠,會產生和上面相同的情況,如果必須使用鎖,則使用spinlock。

3. 執行耗時的任務

中斷處理應該盡可能快,因為核心要響應大量服務和請求,中斷上下文占用cpu時間太長會嚴重影響系統功能。在中斷處理例程中執行耗時任務時,應該交由中斷處理例程底半部來處理。

4. 訪問使用者空間的虛擬位址

因為中斷上下文是和特定程序無關的,它是核心代表硬體執行在核心空間,所以在終端上下文無法訪問使用者空間的虛擬位址

5. 中斷處理例程不應該設定成reentrant(可被並行或遞迴呼叫的例程)。因為中斷發生時,preempt和irq都被disable,直到中斷返回。所以中斷上下文和程序上下文不一樣,中斷處理例程的不同例項,是不允許在smp上併發執行的。

6. 中斷處理例程可以被更高階別的irq中斷。如果想禁止這種中斷,可以將中斷處理例程定義成快速處理例程,相當於告訴cpu,該例程執行時,禁止本地cpu上所有中斷請求。這直接導致的結果是,由於其他中斷被延遲響應,系統效能下降。

核心的乙個基本原則就是:在中斷或者說原子上下文中,核心不能訪問使用者空間,而且核心是不能 睡眠的。也就是說在這種情況下,核心是不能呼叫有可能引起睡眠的任何函式。一般來講原子上下文指的是在中斷或軟中斷中,以及在持有自旋鎖的時候。核心提供 了四個巨集來判斷是否處於這幾種情況裡:

#define in_irq()     (hardirq_count()) //在處理硬中斷中

#define in_softirq()     (softirq_count()) //在處理軟中斷中

#define in_interrupt()   (irq_count()) //在處理硬中斷或軟中斷中

#define in_atomic()     ((preempt_count() & ~preempt_active) != 0) //包含以上所有情況

這四個巨集所訪問的count都是thread_info->preempt_count。這個變數其實是乙個位掩碼。最低8位表示搶占計數,通常由spin_lock/spin_unlock修改,或程式設計師強制修改,同時表明核心容許的最大搶占深度是256。

8-15位表示軟中斷計數,通常由local_bh_disable/local_bh_enable修改,同時表明核心容許的最大軟中斷深度是256。

位16-27是硬中斷計數,通常由enter_irq/exit_irq修改,同時表明核心容許的最大硬中斷深度是4096。

第28位是preempt_active標誌。用**表示就是:

preempt_mask: 0x000000ff

softirq_mask: 0x0000ff00

hardirq_mask: 0x0fff0000

凡是上面4個巨集返回1得到地方都是原子上下文,是不容許核心訪問使用者空間,不容許核心睡眠的,不容許呼叫任何可能引起睡眠的函式。而且代表thread_info->preempt_count不是0,這就告訴核心,在這裡面搶占被禁用。

但 是,對於in_atomic()來說,在啟用搶占的情況下,它工作的很好,可以告訴核心目前是否持有自旋鎖,是否禁用搶占等。但是,在沒有啟用搶占的情況 下,spin_lock根本不修改preempt_count,所以即使核心呼叫了spin_lock,持有了自旋鎖,in_atomic()仍然會返回 0,錯誤的告訴核心目前在非原子上下文中。所以凡是依賴in_atomic()來判斷是否在原子上下文的**,在禁搶占的情況下都是有問題的。

程序上下文 中斷上下文及原子上下文

談論程序上下文 中斷上下文 原子上下文之前,有必要討論下兩個概念 a 上下文 上下文是從英文context翻譯過來,指的是一種環境。相對於程序而言,就是程序執行時的環境 具體來說就是各個變數和資料,包括所有的暫存器變數 程序開啟的檔案 記憶體資訊等。b 原子 原子 atom 本意是 不能被進一步分割...

中斷上下文 程序上下文

在學習與作業系統相關的知識時候,我們經常遇到程序上下文 中斷上下文,看似熟悉又感覺不是特別清晰。這裡我們從如下幾個方面進行描述。上下文是從英文中context翻譯過來的,指的是一種環境。上下文我們看起來不怎麼熟悉,但是我們可以看context的中文翻譯,或者我們能更加的情形些。context n 語...

程序上下文和中斷上下文

程序上下文和中斷上下文是作業系統中很重要的兩個概念,這兩個概念在作業系統課程中不斷被提及,是最經常接觸 看上去很懂但又說不清楚到底怎麼回事。造成這種局面的原因,可能是原來接觸到的作業系統課程的教學總停留在一種淺層次的理論層面上,沒有深入去研究。處理器總處於以下狀態中的一種 核心態,執行於程序上下文,...