① linux的進程優先順序 NI 和 PR 有什麼區別
用top -u 命令查看進程以及PID。命令如下:
$ top -u
PID — 進程id
USER — 進程所有者
PR — 進程優先順序
NI — nice值。負值表示高優先順序,正值表示低優先順序
VIRT — 進程使用的虛擬內存總量,單位kb。VIRT=SWAP+RES
RES — 進程使用的、未被換出的物理內存大小,單位kb。RES=CODE+DATA
SHR — 共享內存大小,單位kb
S — 進程狀態。D=不可中斷的睡眠狀態 R=運行 S=睡眠 T=跟蹤/停止 Z=僵屍進程
%CPU — 上次更新到現在的CPU時間佔用百分比
%MEM — 進程使用的物理內存百分比
TIME+ — 進程使用的CPU時間總計,單位1/100秒
COMMAND — 進程名稱(命令名/命令行)
② linux 用戶進程 可以搶占內核進程嗎
1.2.1 調度過程中關閉內核搶占
我們在上一篇linux內核主調度器schele(文章鏈接, CSDN, Github)中在分析主調度器的時候, 我們會發現內核在進行調度之前都會通過preempt_disable關閉內核搶占, 而在完成調度工作後, 又會重新開啟內核搶占
參見主調度器函數schele
do {
preempt_disable(); /* 關閉內核搶占 */
__schele(false); /* 完成調度 */
sched_preempt_enable_no_resched(); /* 開啟內核搶占 */
} while (need_resched()); /* 如果該進程被其他進程設置了TIF_NEED_RESCHED標志,則函數重新執行進行調度 */123456123456
這個很容易理解, 我們在內核完成調度器過程中, 這時候如果發生了內核搶占, 我們的調度會被中斷, 而調度卻還沒有完成, 這樣會丟失我們調度的信息.
1.2.2 調度完成檢查need_resched看是否需要重新調度
而同樣我們可以看到, 在調度完成後, 內核會去判斷need_resched條件, 如果這個時候為真, 內核會重新進程一次調度.
這個的原因, 我們在前一篇博客中, 也已經說的很明白了,
內核在thread_info的flag中設置了一個標識來標志進程是否需要重新調度, 即重新調度need_resched標識TIF_NEED_RESCHED, 內核在即將返回用戶空間時會檢查標識TIF_NEED_RESCHED標志進程是否需要重新調度,如果設置了,就會發生調度, 這被稱為用戶搶占
2 非搶占式和可搶占式內核
為了簡化問題,我使用嵌入式實時系統uC/OS作為例子
首先要指出的是,uC/OS只有內核態,沒有用戶態,這和Linux不一樣
多任務系統中, 內核負責管理各個任務, 或者說為每個任務分配CPU時間, 並且負責任務之間的通訊.
內核提供的基本服務是任務切換. 調度(Scheler),英文還有一詞叫dispatcher, 也是調度的意思.
這是內核的主要職責之一, 就是要決定該輪到哪個任務運行了. 多數實時內核是基於優先順序調度法的, 每個任務根據其重要程度的不同被賦予一定的優先順序. 基於優先順序的調度法指,CPU總是讓處在就緒態的優先順序最高的任務先運行. 然而, 究竟何時讓高優先順序任務掌握CPU的使用權, 有兩種不同的情況, 這要看用的是什麼類型的內核, 是不可剝奪型的還是可剝奪型內核
2.1 非搶占式內核
非搶占式內核是由任務主動放棄CPU的使用權
非搶占式調度法也稱作合作型多任務, 各個任務彼此合作共享一個CPU. 非同步事件還是由中斷服務來處理. 中斷服務可以使一個高優先順序的任務由掛起狀態變為就緒狀態.
但中斷服務以後控制權還是回到原來被中斷了的那個任務, 直到該任務主動放棄CPU的使用權時,那個高優先順序的任務才能獲得CPU的使用權。非搶占式內核如下圖所示.
非搶占式內核的優點有
中斷響應快(與搶占式內核比較);
允許使用不可重入函數;
幾乎不需要使用信號量保護共享數據, 運行的任務佔有CPU,不必擔心被別的任務搶占。這不是絕對的,在列印機的使用上,仍需要滿足互斥條件。
非搶占式內核的缺點有
任務響應時間慢。高優先順序的任務已經進入就緒態,但還不能運行,要等到當前運行著的任務釋放CPU
非搶占式內核的任務級響應時間是不確定的,不知道什麼時候最高優先順序的任務才能拿到CPU的控制權,完全取決於應用程序什麼時候釋放CPU
2.2 搶占式內核
使用搶占式內核可以保證系統響應時間. 最高優先順序的任務一旦就緒, 總能得到CPU的使用權。當一個運行著的任務使一個比它優先順序高的任務進入了就緒態, 當前任務的CPU使用權就會被剝奪,或者說被掛起了,那個高優先順序的任務立刻得到了CPU的控制權。如果是中斷服務子程序使一個高優先順序的任務進入就緒態,中斷完成時,中斷了的任務被掛起,優先順序高的那個任務開始運行。
搶占式內核如下圖所示
搶占式內核的優點有
使用搶占式內核,最高優先順序的任務什麼時候可以執行,可以得到CPU的使用權是可知的。使用搶占式內核使得任務級響應時間得以最優化。
搶占式內核的缺點有:
不能直接使用不可重入型函數。調用不可重入函數時,要滿足互斥條件,這點可以使用互斥型信號量來實現。如果調用不可重入型函數時,低優先順序的任務CPU的使用權被高優先順序任務剝奪,不可重入型函數中的數據有可能被破壞。
3 linux用戶搶占
3.1 linux用戶搶占
當內核即將返回用戶空間時, 內核會檢查need_resched是否設置, 如果設置, 則調用schele(),此時,發生用戶搶占.
3.2 need_resched標識
內核如何檢查一個進程是否需要被調度呢?
內核在即將返回用戶空間時檢查進程是否需要重新調度,如果設置了,就會發生調度, 這被稱為用戶搶占, 因此內核在thread_info的flag中設置了一個標識來標志進程是否需要重新調度, 即重新調度need_resched標識TIF_NEED_RESCHED
並提供了一些設置可檢測的函數
函數
描述
定義
set_tsk_need_resched 設置指定進程中的need_resched標志 include/linux/sched.h, L2920
clear_tsk_need_resched 清除指定進程中的need_resched標志 include/linux/sched.h, L2926
test_tsk_need_resched 檢查指定進程need_resched標志 include/linux/sched.h, L2931
而我們內核中調度時常用的need_resched()函數檢查進程是否需要被重新調度其實就是通過test_tsk_need_resched實現的, 其定義如下所示
// http://lxr.free-electrons.com/source/include/linux/sched.h?v=4.6#L3093
static __always_inline bool need_resched(void)
{
return unlikely(tif_need_resched());
}
// http://lxr.free-electrons.com/source/include/linux/thread_info.h?v=4.6#L106
#define tif_need_resched() test_thread_flag(TIF_NEED_RESCHED)1234567812345678
3.3 用戶搶占的發生時機(什麼時候需要重新調度need_resched)
一般來說,用戶搶占發生幾下情況:
從系統調用返回用戶空間;
從中斷(異常)處理程序返回用戶空間
從這里我們可以看到, 用戶搶占是發生在用戶空間的搶占現象.
更詳細的觸發條件如下所示, 其實不外乎就是前面所說的兩種情況: 從系統調用或者中斷返回用戶空間
時鍾中斷處理常式檢查當前任務的時間片,當任務的時間片消耗完時,scheler_tick()函數就會設置need_resched標志;
信號量、等到隊列、completion等機制喚醒時都是基於waitqueue的,而waitqueue的喚醒函數為default_wake_function,其調用try_to_wake_up將被喚醒的任務更改為就緒狀態並設置need_resched標志。
設置用戶進程的nice值時,可能會使高優先順序的任務進入就緒狀態;
改變任務的優先順序時,可能會使高優先順序的任務進入就緒狀態;
新建一個任務時,可能會使高優先順序的任務進入就緒狀態;
對CPU(SMP)進行負載均衡時,當前任務可能需要放到另外一個CPU上運行
4 linux內核搶占
4.1 內核搶占的概念
對比用戶搶占, 顧名思義, 內核搶占就是指一個在內核態運行的進程, 可能在執行內核函數期間被另一個進程取代.
4.2 為什麼linux需要內核搶占
linux系統中, 進程在系統調用後返回用戶態之前, 或者是內核中某些特定的點上, 都會調用調度器. 這確保除了一些明確指定的情況之外, 內核是無法中斷的, 這不同於用戶進程.
如果內核處於相對耗時的操作中, 比如文件系統或者內存管理相關的任務, 這種行為可能會帶來問題. 這種情況下, 內核代替特定的進程執行相當長的時間, 而其他進程無法執行, 無法調度, 這就造成了系統的延遲增加, 用戶體驗到」緩慢」的響應. 比如如果多媒體應用長時間無法得到CPU, 則可能發生視頻和音頻漏失現象.
在編譯內核時如果啟用了對內核搶占的支持, 則可以解決這些問題. 如果高優先順序進程有事情需要完成, 那麼在啟用了內核搶占的情況下, 不僅用戶空間應用程序可以被中斷, 內核也可以被中斷,
linux內核搶占是在Linux2.5.4版本發布時加入的, 盡管使內核可搶占需要的改動特別少, 但是該機制不像搶佔用戶空間進程那樣容易實現. 如果內核無法一次性完成某些操作(例如, 對數據結構的操作), 那麼可能出現靜態條件而使得系統不一致.
內核搶占和用戶層進程被其他進程搶占是兩個不同的概念, 內核搶佔主要是從實時系統中引入的, 在非實時系統中的確也能提高系統的響應速度, 但也不是在所有情況下都是最優的,因為搶占也需要調度和同步開銷,在某些情況下甚至要關閉內核搶占, 比如前面我們將主調度器的時候, linux內核在完成調度的過程中是關閉了內核搶占的.
內核不能再任意點被中斷, 幸運的是, 大多數不能中斷的點已經被SMP實現標識出來了. 並且在實現內核搶占時可以重用這些信息. 如果內核可以被搶占, 那麼單處理器系統也會像是一個SMP系統
4.3 內核搶占的發生時機
要滿足什麼條件,kernel才可以搶佔一個任務的內核態呢?
沒持有鎖。鎖是用於保護臨界區的,不能被搶占。
Kernel code可重入(reentrant)。因為kernel是SMP-safe的,所以滿足可重入性。
內核搶占發生的時機,一般發生在:
當從中斷處理程序正在執行,且返回內核空間之前。當一個中斷處理常式退出,在返回到內核態時(kernel-space)。這是隱式的調用schele()函數,當前任務沒有主動放棄CPU使用權,而是被剝奪了CPU使用權。
當內核代碼再一次具有可搶占性的時候,如解鎖(spin_unlock_bh)及使能軟中斷(local_bh_enable)等, 此時當kernel code從不可搶占狀態變為可搶占狀態時(preemptible again)。也就是preempt_count從正整數變為0時。這也是隱式的調用schele()函數
如果內核中的任務顯式的調用schele(), 任務主動放棄CPU使用權
如果內核中的任務阻塞(這同樣也會導致調用schele()), 導致需要調用schele()函數。任務主動放棄CPU使用權
內核搶占,並不是在任何一個地方都可以發生,以下情況不能發生
內核正進行中斷處理。在Linux內核中進程不能搶佔中斷(中斷只能被其他中斷中止、搶占,進程不能中止、搶佔中斷),在中斷常式中不允許進行進程調度。進程調度函數schele()會對此作出判斷,如果是在中斷中調用,會列印出錯信息。
內核正在進行中斷上下文的Bottom Half(中斷下半部,即軟中斷)處理。硬體中斷返回前會執行軟中斷,此時仍然處於中斷上下文中。如果此時正在執行其它軟中斷,則不再執行該軟中斷。
內核的代碼段正持有spinlock自旋鎖、writelock/readlock讀寫鎖等鎖,處干這些鎖的保護狀態中。內核中的這些鎖是為了在SMP系統中短時間內保證不同CPU上運行的進程並發執行的正確性。當持有這些鎖時,內核不應該被搶占。
內核正在執行調度程序Scheler。搶占的原因就是為了進行新的調度,沒有理由將調度程序搶佔掉再運行調度程序。
內核正在對每個CPU「私有」的數據結構操作(Per-CPU date structures)。在SMP中,對於per-CPU數據結構未用spinlocks保護,因為這些數據結構隱含地被保護了(不同的CPU有不一樣的per-CPU數據,其他CPU上運行的進程不會用到另一個CPU的per-CPU數據)。但是如果允許搶占,但一個進程被搶占後重新調度,有可能調度到其他的CPU上去,這時定義的Per-CPU變數就會有問題,這時應禁搶占。
③ Linux的進程優先順序NI和PR有什麼區別
nice(NI)和priority(PR),並不是同一個概念。
NICE值應該是熟悉Linux/UNIX的人很了解的概念了,它是反應一個進程「優先順序」狀態的值,其取值范圍是-20至19,一共40個級別。這個值越小,表示進程」優先順序」越高,而值越大「優先順序」越低。nice值雖然不是priority,但是它確實可以影響進程的優先順序。一般會把nice值叫做靜態優先順序,這也基本符合nice值的特點,就是當nice值設定好了之後,除非我們用renice去改它,否則它是不變的。
實用priority值表示PRI和PR值,或者叫動態優先順序。priority的值在之前內核的O1調度器上表現是會變化的,所以也叫做動態優先順序。在內核中,進程優先順序的取值范圍是通過一個宏定義的,這個宏的名稱是MAX_PRIO,它的值為140。
而這個值又是由另外兩個值相加組成的,一個是代表nice值取值范圍的NICE_WIDTH宏,另一個是代表實時進程(realtime)優先順序范圍的MAX_RT_PRIO宏。
說白了就是,Linux實際上實現了140個優先順序范圍,取值范圍是從0-139,這個值越小,優先順序越高。nice值的-20到19,映射到實際的優先順序范圍是100-139。
④ Pc/xt能向cpu發出中斷請求信號的是
計算機通常有很多輸入輸出設備,當這些設備需要服務時就向處理器提出要求,處理器在收到要求後就為這些設備提供服務。
當設備向處理器提出服務要求時,處理器會在執行完當前一條指令後相應設備要求,轉向並執行相應的服務程序(中斷服務程序ISR),在執行完畢後,處理器回返回到執行ISR之前的程序繼續執行,這種處理方式即為中斷方法,設備提出的請求稱為中斷請求(IRQ)。
在微處理器中,由可編程控制器(Programmable Interrupt Controller,PIC)負責管理系統中的中斷請求。它通過連接到設備的中斷請求引腳來接受設備發車的中斷請求,當設備需要服務時,就激活中斷請求引腳信號,PIC檢測到信號後即向CPU發出中斷信號。此時有三種情況:
1)PIC僅僅接收到1個中斷請求信號,而此時CPU沒有執行中斷請求,那麼PIC就直接向CPU發出中斷信號。
2)PIC同時收到多個中斷請求信號,而此時CPU沒有執行中斷請求,那麼PIC比較中斷請求信號中的優先順序,選擇優先順序最高的向CPU發出中斷信號。
3)PIC收到多個中斷請求信號,此時CPU正在執行中斷服務程序,那麼PIC選出的最高優先順序的中斷請求信號然後再與正在執行的中斷服務進行比較,基於比較結果來決定是否向CPU立刻發送中斷信號。
但PIC向CPU的INT引腳發送中斷信號時,CPU會立刻停下來並詢問PIC要執行哪個中斷服務請求。PIC則通過向數據匯流排發送與中斷請求對應的中斷號告知CPU執行哪個中斷服務程序。CPU通過在數據匯流排讀取的中斷號,查詢中斷向量表,取得相應的中斷服務程序的地址並開始執行中斷服務程序,執行完畢後,處理器就接著執行被中斷的程序。
上面所述是描述的I/O設備的中斷處理過程,屬於硬體中斷的范疇,但是中斷並非只有硬體,也可用於軟體,通過使用int指令並使用其操作數指明中斷號,就可以讓CPU執行相應的ISR。
兩片8259A晶元共可處理15級中斷,從晶元的INT引腳連接到主晶元的IR2引腳上,即從晶元發出的中斷信號做為主晶元IRQ2輸入信號。主晶元的埠地址是0x20,從晶元的埠基地址是0xA0,IRQ9引腳的作用與PC/XT的IRQ2相同(PC/AT和PC/XT對應8086系列的不同數據匯流排,PC/XT是早期的型號,數據匯流排為8位,而PC/AT的數據匯流排為16位),即PC/AT機利用硬體電路把使用IRQ2的設備的IRQ2引腳重新定性到了PIC的IRQ9引腳上,並利用BIOS中的軟體把IRQ9的中斷int 71重新定向到IRQ2的中斷 int 0x0A,這樣使得使用IRQ2的PC/XT的8位設配卡在PC/AT機下仍能正常使用,做到了向下兼容。
在匯流排控制器的控制下,晶元有兩種狀態:編程狀態和操作狀態。編程狀態是CPU通過IN和OUT指令對晶元進行初始化編程的狀態,完成了初始化編程後,晶元就進入操作狀態。此時晶元可隨時響應外部設備提出的中斷請求(IRQ0-IRQ15)。通過中斷判優選擇,晶元選擇最高優先順序的中斷請求作為服務對象,通過CPU的INT引腳向CPU發出中斷請求,CPU響應後,晶元從數據匯流排D7-D0將編程設定的對應中斷請求的中斷號送出,CPU接收到中斷號,查找中斷向量表,從而響應中斷。
8086中斷子系統
8086的微型機系統中採用的是8259A可編程中斷控制器晶元,每個晶元可以管理8個中斷源,通過多級相連,可以管理多個中斷向量。PC/AT系列使用了兩片上述晶元,如下圖所示:
中斷向量表
中斷向量表有時也稱為中斷描述符表,它的作用就是通過中斷號來確定對應中斷的ISR的物理地址。8086微機支持256個中斷,在實模式下,每個中斷向量由4個位元組組成,這四個位元組指明了中斷服務程序的段值和段內偏移,因此整個中斷向量表的大小為256*4位元組=1024位元組。當8086微機啟動時,ROM BIOS中的程序會在物理內存的0x0000:0x0000處初始化並設置中斷向量表,各中斷的默認ISR在BIOS中給出。中斷向量表中的向量是按照中斷號順序排列,因此給定中斷號N,對應的物理地址則為:0x0000:N*4(位元組)。
BIOS的初始化操作設置了8259A晶元支持的16個硬體中斷向量和BIOS提供的中斷號為0x10-0x1f的中斷調用功能向量等。對於實際沒有使用的向量則填入臨時的啞中斷服務程序的地址,在系統引導載入操作系統時會根據實際需要修改某些中斷向量的值。
對於Linux操作系統,在載入內核時需要用到BIOS提供的顯示和磁碟讀操作中斷功能,在內核正常工作之前則會在setup.s程序中重新初始化8259A晶元並且在head.s程序中重新設置一張中斷向量表(即中斷描述符),完全拋棄了在BIOS中提供的中斷服務功能。
在intel CPU運行在32位保護模式下時,需要使用中斷描述符表IDT來管理中斷或者異常。IDT是中斷向量表的替代物,作用類似於中斷向量,只不過除了含有中斷服務程序ISR的地址外,還包括了有關特權級和描述符類別等信息。
Linux內核的中斷處理
對linux內核來說,中斷信號分為兩類:硬體中斷和軟體中斷(異常),中斷用0-255之間的數字標示,其中int0-int31(0x00-0x1f)每個中斷的功能由intel公司固定設定或者保留,屬於軟體中斷(異常),這些中斷是在CPU執行指令時探測到異常情況而引起的。通常還可分為故障和陷阱兩類,中斷int32-int255(0x20-0xff)可以由用戶自己設定。
中斷int32-int47對應8259A中斷控制晶元發出的硬體中斷請求信號IRQ0-IRQ15。
程序編程發出的系統調用中斷設置為int128(0x80),系統調用中斷是用戶程序使用操作系統資源的唯一界面介面。
系統在初始化時,內核首先在head.s中使用一個「啞中斷向量(中斷描述符)」對中斷描述符表中的所有的256個描述符進行默認設置。這個啞中斷向量執行一個默認的「無中斷」處理程序。此時發生中斷而執行此程序時會顯示信息:「未知中斷(Unknown interrupt)」。這樣使用啞中斷向量的目的是為了防止出現一般保護性錯誤。
而對於系統中需要使用的中斷則會在初始化過程中的init/main.c程序中重新設置這些中斷描述符(即中斷向量),讓他們指向對應的實際處理程序。通常對int0-int31的初始化設置在traps.c程序中進行重新設置;系統調用中斷int128的重新設置在kernel/sched.c中進行。
Linux內核設置IDT時使用了中斷門和陷阱門兩種描述符。區別是對標志寄存器EFLAGS中的「中斷允許標志」IF的影響,中斷門執行的中斷會復位IF標志,可以避免其他中斷干擾當前中斷的處理,隨後的中斷結束指令iret會從堆棧上恢復IF標志的原值,而陷阱門執行的中斷不會影響IF標志。
⑤ 關於嵌入式系統線程調度與優先順序的問題,wince或linux
你剛講了線程1的優秀級高,那麼中斷來了之後,肯定要先處理這個線程。
系統不會強制結束當前的線程,如果這樣做可能導致死機活崩潰,因為該線程可能是系統的。
正常的做法是將該線程的數據備份,處理優先順序高的,之後再回來繼續工作
⑥ Linux 系統中的中斷是不是沒有中斷優先順序
關於中斷嵌套:在linux內核里,如果驅動在申請注冊中斷的時候沒有特別的指定,do_irq在做中斷響應的時候,是開啟中斷的,如果在驅動的中斷處理函數正在執行的過程中,出現同一設備的中斷或者不同設備的中斷,這時候新的中斷會被立即處理,還是被pending,等當前中斷處理完成後,再做處理。在2.4和2.6內核里,關於這一塊是否有什麼不同。 一般申請中斷的時候都允許開中斷,即不使用SA_INTERRUPT標志。如果允許共享則加上 SA_SHIRQ,如果可以為內核熵池提供熵值(譬如你寫的驅動是ide之類的驅動),則再加上 SA_SAMPLE_RANDOM標志。這是普通的中斷請求過程。對於這種一般情況,只要發生中斷,就可以搶占內核,即使內核正在執行其他中斷函數。這里有兩點說明:一是因為linux不支持 中斷優先順序,因此任何中斷都可以搶占其他中斷,但是同種類型的中斷(即定義使用同一個 中斷線的中斷)不會發生搶占,他們會在執行本類型中斷的時候依次被調用執行。二是所謂 只要發生中斷,就可以搶占內核這句是有一定限制的,因為當中斷發生的時候系統由中斷門 進入時自動關中斷(對於x86平台就是將eflags寄存器的if位置為0),只有當中斷函數被執行 (handle_IRQ_event)的過程中開中斷之後才能有搶占。 對於同種類型的中斷,由於其使用同樣的idt表項,通過其狀態標志(IRQ_PENDING和 IRQ_INPROGRESS)可以防止同種類型的中斷函數執行(注意:是防止handle_IRQ_event被重入, 而不是防止do_IRQ函數被重入),對於不同的中斷,則可以自由的嵌套。因此,所謂中斷嵌套, 對於不同的中斷是可以自由嵌套的,而對於同種類型的中斷,是不可以嵌套執行的。以下簡單解釋一下如何利用狀態標志來防止同種類型中斷的重入:當某種類型的中斷第一次發生時,首先其idt表項的狀態位上被賦予IRQ_PENDING標志,表示有待處理。 然後將中斷處理函數action置為null,然後由於其狀態沒有IRQ_INPROGRESS標志(第一次),故將其狀態置上IRQ_INPROGRESS並去處IRQ_PENDING標志,同時將action賦予相應的中斷處理函數指針(這里是一個重點,linux很巧妙的用法,隨後說明)。這樣,後面就可以順利執行handle_IRQ_event進行中斷處理,當在handle_IRQ_event中開中斷後,如果有同種類型的中斷發生,則再次進入do_IRQ函數,然後其狀態位上加上IRQ_PENDING標志,但是由於前一次中斷處理中加上的IRQ_INPROGRESS沒有被清除,因此這里無法清除IRQ_PENDING標志,因此action還是為null,這樣就無法再次執行handle_IRQ_event函數。從而退出本次中斷處理,返回上一次的中斷處理函數中,即繼續執行handle_IRQ_event函數。當handle_IRQ_event返回時檢查IRQ_PENDING標志,發現存在這個標志,說明handle_IRQ_event執行過程中被中斷過,存在未處理的同類中斷,因此再次循環執行handle_IRQ_event函數。直到不存在IRQ_PENDING標志為止。2.4和2.6的差別,就我來看,主要是在2.6中一進入do_IRQ,多了一個關閉內核搶占的動作,同時在處理中多了一種對IRQ_PER_CPU類型的中斷的處理,其他沒有什麼太大的改變。這類IRQ_PER_CPU的中斷主要用在smp環境下將中斷綁定在某一個指定的cpu上。例如arch/ppc/syslib/open_pic.c中的openpic_init中初始化ipi中斷的時候。 其實簡單的說,中斷可以嵌套,但是同種類型的中斷是不可以嵌套的,因為在IRQ上發生中斷,在中斷響應的過程中,這個IRQ是屏蔽的,也就是這個IRQ的中斷是不能被發現的。 同時在內核的臨界區內,中斷是被禁止的 關於do_IRQ可能會丟失中斷請求:do_IRQ函數是通過在執行完handle_IRQ_event函數之後判斷status是否被設置了IRQ_PENDING標志來判斷是否還有沒有被處理的同一通道的中斷請求。 但是這種方法只能判斷是否有,而不能知道有多少個未處理的統一通道中斷請求。也就是說,假如在第一個中斷請求執行handle_IRQ_event函數的過程中來了同一通道的兩個或更多中斷請求,而這些中斷不會再來,那麼僅僅通過判斷status是否設置了IRQ_PENDING標志不知道到底有多少個未處理的中斷,handle_IRQ_event只會被再執行一次。這算不算是個bug呢? 不算,只要知道有中斷沒有處理就OK了,知道1個和知道N個,本質上都是一樣的。作為外設,應當能夠處理自己中斷未被處理的情況。不可能丟失的,在每一個中斷描述符的結構體內,都有一個鏈表,鏈表中存放著服務常式序關於中斷中使用的幾個重要概念和關系: 一、基本概念 1. 產生的位置 發生的時刻 時序 中斷 CPU外部 隨機 非同步 異常 CPU正在執行的程序 一條指令終止執行後 同步 2.由中斷或異常執行的代碼不是一個進程,而是一個內核控制路徑,代表中斷發生時正在運行的進程的執行 中斷處理程序與正在運行的程序無關 引起異常處理程序的進程正是異常處理程序運行時的當前進程 二、特點 (2)能以嵌套的方式執行,但是同種類型的中斷不可以嵌套 (3)盡可能地限制臨界區,因為在臨界區中,中斷被禁止 2.大部分異常發生在用戶態,缺頁異常是唯一發生於內核態能觸發的異常 缺頁異常意味著進程切換,因此中斷處理程序從不執行可以導致缺頁的操作 3.中斷處理程序運行於內核態 中斷發生於用戶態時,要把進程的用戶空間堆棧切換到進程的系統空間堆棧,剛切換時,內核堆棧是空的 中斷發生於內核態時, 不需要堆棧空間的切換 三、分類 1.中斷的分類:可屏蔽中斷、不可屏蔽中斷 2.異常的分類: 分類 解決異常的方法 舉例 故障 那條指令會被重新執行 缺頁異常處理程序 陷阱 會從下一條指令開始執行 調試程序
⑦ linux進程處於內核態會被更高優先順序搶占嗎
內核態搶占(Kernel
Preemption)
在2.6
kernel以前,kernelcode(中斷和系統調用屬於kernel
code)會一直運行,直到code被完成或者被阻塞(系統調用可以被阻塞)。在
2.6kernel里,Linuxkernel變成可搶占式。當從中斷處理常式返回到內核態(kernel-space)時,kernel會檢查是否可以搶占和是否需要重新調度。kernel可以在任何時間點上搶佔一個任務(因為中斷可以發生在任何時間點上),只要在這個時間點上kernel的狀態是安全的、可重新調度的。