2013-08-23 90 views
0

所有的Unix內核都是可重入的:幾個進程可能同時在內核 模式下執行。我如何才能在代碼中實現這種效果?我應該如何處理許多進程調用系統調用的情況,在內核模式下掛起?Linux內核如何實現重入?

回答

1

[編輯 - 術語「折返」在得到幾個不同的感官的使用。這個答案使用基本的「多個上下文可以同時執行相同的代碼」。這通常適用於單個例程,但可以擴展爲適用於一組協作例程,通常是共享數據的例程。這是一個極端的例子,當應用到一個完整的程序 - 一個Web服務器,或一個操作系統。如果網絡服務器一次只能與一個客戶端進行交易,則該網絡服務器可能被認爲是不可重入的。 (呃!)如果一次只有一個進程/線程/處理器可以執行內核代碼,那麼操作系統內核可能被稱爲不可重入。

像操作系統過渡到多處理器系統中發生。許多經歷了從單寫處理器到單鎖保護的緩慢過渡,即通過更精細和更細粒度鎖定的各個階段的一切(即不可重入)。 IIRC,Linux終於擺脫了「大內核鎖」在約。版本2.6.37 - 但在此之前大部分時間已經過去,只是保護尚未轉換爲多處理實現的殘留。

這個答案的其餘部分是寫在各個程序的條款,而不是完整的程序。]

如果你是在用戶空間中,你不需要做任何事情。你打電話給你想要的任何系統調用,併發生正確的事情。

所以我要相信你是問有關在內核代碼。

從概念上講,這很簡單。當多線程調用相同的子例程時,它與用戶空間中多線程程序中發生的情況幾乎相同。 (讓我們假設這是一個C程序 - 其他語言可能有不同的命名機制。)

當系統調用實現使用自動(堆棧)變量時,它有自己的副本 - 沒有重入問題。當需要使用全局數據時,通常需要使用某種鎖定 - 所需的特定鎖定取決於所使用的特定數據以及它對數據執行的操作。

這都是很普通的,因此,或許一個例子可能會有幫助。

比方說,系統調用要修改過程的一些屬性。該過程由struct task_struct表示,其是各種鏈接列表的成員。這些鏈接列表受tasklist_lock保護。您的系統調用獲取tasklist_lock,找到正確的進程,可能獲得每進程鎖定控制其關心的字段,修改該字段並刪除兩個鎖。

還有一個細節,這是執行進程不同的系統調用的情況,它們不互相共享數據。通過合理的實施,根本沒有衝突。一個進程可以進入內核來處理系統調用,而不影響其他進程。我不記得專門看linux的實現,但我想它是「合理的」。類似陷入到異常處理程序中的陷阱,該異常處理程序查找表以找到處理所請求的特定系統調用的子例程。該表有效地爲const,因此不需要鎖。

+0

你覺得下面的網站怎麼說? [鏈接] http://linux.omnipotent.net/article.php?article_id = 12496&page = -1 –

+0

我撇清了它,雖然它有一些有用的想法,但我覺得它使得一個簡單的概念太複雜了。 「可重入」幾乎意味着多個上下文(進程)可以同時處於同一個例程中,而不會產生奇怪的影響。最初,它往往意味着可以安全地調用例程(它可以調用它自己),因爲系統只有一個處理器,線程還沒有被髮明出來,甚至進程大部分都以批處理模式運行完成。 ... –

+0

Aargh - 評論機制沒有爲此工作 - 我需要編輯答案或添加第二個答案,只是討論術語「可重入」的含義和歷史。所引用的文章和我正從不同的角度接近。 –