2016-03-28 46 views
7

我嘗試瞭解使用mmap將Linux內核模式空間映射到用戶模式空間的機制。內存映射的解剖結構內核空間

首先我有一個可加載的內核模塊(LKM),它提供了一個具有mmap功能的字符設備。然後用戶空間應用程序打開設備並調用mmap LKM在內核模式空間(虛擬高地址)內的LKM堆上分配內存空間。在用戶空間一側,數據指針指向一個虛擬低地址。

下圖顯示了我如何想象記憶的解剖結構。這是正確的嗎?

Memory mapping

請讓我知道,如果問題不明確,我將嘗試添加更多的細節。


編輯:圖片被編輯爲有關吉爾漢密爾頓。黑色箭頭現在指向一個物理地址。

+2

是。這基本上是正確的。我會用黑色的箭頭指向右邊。也就是說,它共享相同的物理頁面。它不會獲得與內核相同的虛擬地址,也不會以某種方式「指向」內核數據區域。相反,它會自己獨立映射到相同的物理內存頁面。 –

+0

通常我可以看到Linux中的每個線程都有自己的虛擬內存區域,分爲1GB內核和3GB用戶空間。在這種情況下:內核模塊的某些部分是否位於用戶空間應用程序的內核空間部分? – Alex44

+1

是的。在該模型中,內核虛擬地址空間是最高1GB(x86 32位)。用戶模式空間最低3GB。所以他們共享4GB虛擬地址空間。當存在上下文切換時,將安裝新的頁面表。它與頂部1GB具有相同的映射,但新過程的用戶模式映射爲新映射。但是,用戶模式永遠不能訪問最高1GB(即,如果它嘗試訪問該內存,由於頁表訪問限制,它將收到「SIGSEGV」)。內核模式*可以*技術上直接訪問用戶模式空間,儘管它通常是通過API完成的。 –

回答

0

繪圖丟失了一些重要的基本假設。

內核不需要mmap()來訪問用戶空間內存。如果用戶進程具有內存,則它已按照定義映射到地址空間中。從這個意義上說,內存已經在用戶和內核之間共享。

mmap()在用戶的虛擬地址空間中創建一個新的區域,這樣如果以後訪問,地址區域可以由物理內存填充。內存的實際分配和修改頁表項是由內核完成的。

mmap()僅適用於管理用戶一半的虛擬地址空間。內核地址空間的一半是完全不同的。

此外,系統中的所有進程都共享內核的一半。每個進程都有其專用的虛擬地址空間,但對頁表進行編程時,對於所有進程而言,內核半頁的頁表條目設置完全相同。

此外,內核不會mmap()爲了訪問用戶空間內存。 mmap()是由內核提供給用戶的一項服務,用於修改用戶虛擬地址空間中的當前映射。

順便說一句,內核實際上有幾種方法來訪問用戶的內存,如果它想。首先,內核具有內核地址空間的專用區域(作爲其內核空間的一部分),其以連續方式映射整個物理內存。 (在所有64位系統中都是如此,在32位系統中,內核必須實時重映射)

其次,如果內核是通過系統調用或異常進入的,而不是通過硬件中斷,你有有效的進程上下文,所以內核可以直接「取消引用」用戶空間指針來獲得正確的值。第三,如果內核想要在借用的上下文(如中斷處理程序)中執行時考慮進程的用戶空間指針,那麼內核可以通過遍歷vm_area_struct樹以獲取權限並將頁表漫遊到其他目錄,以跟蹤進程的虛擬地址找出實際的物理頁面框架。

0

您可以通過遍歷當前vma的「struct vm_area_struct」來檢查內存區域。

如果您遍歷頁面表併爲與用戶空間無關的虛擬地址派生映射物理地址,則內存佈局將更加清晰。

除了在該圖中該次要校正, BSS是不是一個段,但段其被嵌入到數據段,參考ELF規範詳情鏈接腳本

相關問題