大內(nèi)核鎖(BKL)現(xiàn)在已經(jīng)成為了一個遙遠(yuǎn)的記憶,但在那么多年里,它都是內(nèi)核開發(fā)社區(qū)面臨的一項(xiàng)棘手問題。然而 BKL 的終結(jié)并不意味著內(nèi)核沒有其他有問題的鎖。近來,已經(jīng)有一些關(guān)注轉(zhuǎn)向了軟中斷鎖(software-interrupt lock)或“下半部鎖”(bottom half lock),因?yàn)樗赡軙趯?shí)時系統(tǒng)上導(dǎo)致延遲。Frederic Weisbecker 正在采取最新行動來減小這個鎖的影響范圍,該方法就是基于移除 BKL 時所采取的方法。
最初,Linux 內(nèi)核是在單處理器系統(tǒng)上開發(fā)的 —— 當(dāng)然可以理解,因?yàn)槟菚r我們手頭只有這種系統(tǒng) —— 因此,代碼在很大程度上基于這樣的假設(shè):它在 CPU 上運(yùn)行,完全不存在其他的 CPU。于是 BKL 最終需要被引入,才能讓 Linux 能夠運(yùn)行在那些產(chǎn)業(yè)分析師向我們保證的未來將會大行其道的多處理器機(jī)器上。它確保了只有一個 CPU 在任何給定時間內(nèi)運(yùn)行內(nèi)核代碼,從而避免了各種并發(fā)問題,但是顯著地犧牲了性能,尤其是隨著 CPU 數(shù)量的增加而更加明顯。人們很快意識到 BKL 必須被移除。
在許多子系統(tǒng)中采取的方法是將 BKL 下移至系統(tǒng)的更底層級別。不再是在調(diào)用每個驅(qū)動程序的 open()函數(shù)時就申請持有 BKL,而是修改每個驅(qū)動程序來自行獲取 BKL。然后,open()函數(shù)可以在不持有 BKL 的情況下安全地得到調(diào)用了,每個驅(qū)動程序可以在需要時進(jìn)行獨(dú)立的審查(audit)和修復(fù),之后可以刪除其對 BKL 的使用。這種把 BKL 下移的動作將一個大問題分解成了許多較小且更易處理的問題。經(jīng)過多年的努力,BKL 終于在 2011 年被移除了。
軟中斷(software interrupt)是一種延后執(zhí)行的方法,用于執(zhí)行一些是緊急但又無法直接在硬件中斷上下文中執(zhí)行的工作。當(dāng)有這種工作要做時,子系統(tǒng)會通過設(shè)置一個 flag 來觸發(fā)軟中斷;這會使得在下一個合適的時機(jī)會調(diào)用其處理程序,通常是在硬件中斷處理完成后就立即調(diào)用,或在從系統(tǒng)調(diào)用返回到用戶空間之前調(diào)用。如果處理時間過長,相關(guān)處理也可以推送到專門的 ksoftirqd 線程中。
軟中斷有許多使用者,包括 tasklets、網(wǎng)絡(luò)、塊設(shè)備子系統(tǒng)、讀-拷貝-更新(RCU)以及內(nèi)核定時器。在某些工作場景中,軟中斷處理可能成為 CPU 總負(fù)載的一個重要部分;它可能會運(yùn)行相當(dāng)長的時間,從而對運(yùn)行在用戶空間中的軟件導(dǎo)致延遲。會禁用軟中斷處理的那些內(nèi)核代碼(為了避免與處理程序的產(chǎn)生 race condition)會變成不可搶占的,這也會導(dǎo)致出現(xiàn)不太愉快的延遲。總之,與 BKL 一樣,軟中斷反映了幾十年前很適用但是現(xiàn)在存在問題的一種設(shè)計(jì)。
其中一個設(shè)計(jì)上的決策是,軟中斷處理程序需要互斥;在任何給定的 CPU 上,只能執(zhí)行一個軟中斷處理程序。因此,如果塊設(shè)備的軟中斷處理程序運(yùn)行時間很長,那么網(wǎng)絡(luò)和定時器處理程序可能就會被無限期地延遲。即使不同類型的軟中斷處理程序之間很少出現(xiàn)競爭,情況仍然是如此。沒有確切的方法可以確定同時運(yùn)行兩個處理程序是否安全,因此人們不會這樣做。
Weisbecker 的 patch set 旨在通過在定時器子系統(tǒng)中采用 BKL 方式的遷移到更底層實(shí)現(xiàn)的方法來解決這個問題。定時器函數(shù)會在內(nèi)核的各個地方被放到隊(duì)列里等待調(diào)用;它們往往是互相獨(dú)立的,與其他軟中斷處理程序并不會產(chǎn)生并發(fā)問題。幾乎所有的定時器函數(shù)都可以與其他軟中斷處理完全并發(fā)地運(yùn)行 —— 但是這里說的是“幾乎”。在沒有確定每個定時器函數(shù)的安全性的情況下,使定時器處理完全獨(dú)立于軟中斷處理可能會引入很難調(diào)試的問題。
相反,Weisbecker 采取了分成兩步的方法來增加定時器處理的并發(fā)性。第一步是允許單個軟中斷向量在不完全禁用軟中斷處理的情況下被禁用。這個 patch set 的目的是允許定時器函數(shù)與其他軟中斷并發(fā)運(yùn)行,但它們?nèi)匀徊粫舜瞬l(fā)運(yùn)行。通過禁用定時器事件的處理(在本地 CPU 上),定時器處理程序可以安全地重新啟用軟中斷處理,而無需擔(dān)心會再次調(diào)用它。
第二步是允許單個 timer 函數(shù)來通知到定時器(timer)子系統(tǒng),說它們可以跟其他軟中斷處理并發(fā)運(yùn)行。任何不會與軟中斷處理程序競爭、或者在需要時得執(zhí)行自己的軟中斷禁用代碼的定時器函數(shù),都可以在設(shè)置其定時器事件時添加 TIMER_SOFTINTERRUPTIBLE flag 來標(biāo)記。當(dāng)定時器子系統(tǒng)看到此標(biāo)志時,就會在該定時器函數(shù)運(yùn)行時重新啟用軟中斷處理。因此,如果出現(xiàn)更重要的工作的話,這個 timer 函數(shù)就可以被搶占。
在 patch set 中只有一個定時器函數(shù) process_timeout()是以這種方式標(biāo)記的。然而,Weisbecker 期待著“幾年后”的一天內(nèi)核的所有定時器函數(shù)都已經(jīng)過 audit,并可以安全地與軟中斷處理程序并發(fā)運(yùn)行;在那時,將可以完全從軟中斷機(jī)制中移除定時器處理。這樣以來就是朝著最終消除軟中斷的一個小步驟。
顯然,需要進(jìn)行相當(dāng)多的工作才能達(dá)到這一點(diǎn)。即使這個 patch set 也需要“更多微調(diào)”,以使可以中斷的 timer 函數(shù)能夠搶占其他軟中斷處理程序,這是解決問題的重要部分。但是,如果這項(xiàng)工作能夠進(jìn)入 mainline 的話,它可能就能代表著朝著這個方向邁出了一步。Weisbecker 現(xiàn)在已經(jīng)嘗試了幾次解決軟中斷的問題,但沒有取得太大的成功。然而最終,就像 BKL 一樣,正確的方法將會被找到,長期存在的問題終將得到解決。
審核編輯:劉清
-
處理器
+關(guān)注
關(guān)注
68文章
18926瀏覽量
227221 -
cpu
+關(guān)注
關(guān)注
68文章
10702瀏覽量
209355 -
定時器
+關(guān)注
關(guān)注
23文章
3218瀏覽量
113676 -
LINUX內(nèi)核
+關(guān)注
關(guān)注
1文章
315瀏覽量
21556 -
軟中斷
+關(guān)注
關(guān)注
0文章
8瀏覽量
3010
原文標(biāo)題:LWN:把軟中斷鎖放到更底層去!
文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論