本篇內(nèi)容主要講解“如何理解Linux系統(tǒng)下的高端內(nèi)存”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“如何理解Linux系統(tǒng)下的高端內(nèi)存”吧!
網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專(zhuān)注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、小程序設(shè)計(jì)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了姑蘇免費(fèi)建站歡迎大家使用!
Linux內(nèi)核地址空間劃分
通常32位Linux內(nèi)核虛擬地址空間劃分0~3G為用戶空間,3~4G為內(nèi)核空間(注意,內(nèi)核可以使用的線性地址只有1G)。注意這里是32位內(nèi)核地址空間劃分,64位內(nèi)核地址空間劃分是不同的。
通常32位Linux內(nèi)核虛擬地址空間劃分0~3G為用戶空間,3~4G為內(nèi)核空間(注意,內(nèi)核可以使用的線性地址只有1G)。注意這里是32位內(nèi)核地址空間劃分,64位內(nèi)核地址空間劃分是不同的。
Linux內(nèi)核高端內(nèi)存的由來(lái)
當(dāng)內(nèi)核模塊代碼或線程訪問(wèn)內(nèi)存時(shí),代碼中的內(nèi)存地址都為邏輯地址,而對(duì)應(yīng)到真正的物理內(nèi)存地址,需要地址一對(duì)一的映射,如邏輯地址0xc0000003對(duì)應(yīng)的物理地址為0×3,0xc0000004對(duì)應(yīng)的物理地址為0×4,… …,邏輯地址與物理地址對(duì)應(yīng)的關(guān)系為
物理地址 = 邏輯地址 – 0xC0000000:這是內(nèi)核地址空間的地址轉(zhuǎn)換關(guān)系,注意內(nèi)核的虛擬地址在“高端”,但是ta映射的物理內(nèi)存地址在低端。
實(shí)際上,“內(nèi)核直接映射空間”也達(dá)不到 1G, 還得留點(diǎn)線性空間給“內(nèi)核動(dòng)態(tài)映射空間” 呢。
因此,Linux 規(guī)定“內(nèi)核直接映射空間” 最多映射 896M 物理內(nèi)存。
對(duì)于高端內(nèi)存,可以通過(guò) alloc_page() 或者其它函數(shù)獲得對(duì)應(yīng)的 page,但是要想訪問(wèn)實(shí)際物理內(nèi)存,還得把 page 轉(zhuǎn)為線性地址才行(為什么?想想 MMU 是如何訪問(wèn)物理內(nèi)存的),也就是說(shuō),我們需要為高端內(nèi)存對(duì)應(yīng)的 page 找一個(gè)線性空間,這個(gè)過(guò)程稱(chēng)為高端內(nèi)存映射。
假 設(shè)按照上述簡(jiǎn)單的地址映射關(guān)系,那么內(nèi)核邏輯地址空間訪問(wèn)為0xc0000000 ~ 0xffffffff,那么對(duì)應(yīng)的物理內(nèi)存范圍就為0×0 ~ 0×40000000,即只能訪問(wèn)1G物理內(nèi)存。若機(jī)器中安裝8G物理內(nèi)存,那么內(nèi)核就只能訪問(wèn)前1G物理內(nèi)存,后面7G物理內(nèi)存將會(huì)無(wú)法訪問(wèn),因?yàn)閮?nèi)核 的地址空間已經(jīng)全部映射到物理內(nèi)存地址范圍0×0 ~ 0×40000000。即使安裝了8G物理內(nèi)存,那么物理地址為0×40000001的內(nèi)存,內(nèi)核該怎么去訪問(wèn)呢?代碼中必須要有內(nèi)存邏輯地址 的,0xc0000000 ~ 0xffffffff的地址空間已經(jīng)被用完了,所以無(wú)法訪問(wèn)物理地址0×40000000以后的內(nèi)存。
顯 然不能將內(nèi)核地址空間0xc0000000 ~ 0xfffffff全部用來(lái)簡(jiǎn)單的地址映射。因此x86架構(gòu)中將內(nèi)核地址空間劃分三部分:ZONE_DMA、ZONE_NORMAL和 ZONE_HIGHMEM。ZONE_HIGHMEM即為高端內(nèi)存,這就是內(nèi)存高端內(nèi)存概念的由來(lái)。
在x86結(jié)構(gòu)中,三種類(lèi)型的區(qū)域(從3G開(kāi)始計(jì)算)如下:
ZONE_DMA 內(nèi)存開(kāi)始的16MB
ZONE_NORMAL 16MB~896MB
ZONE_HIGHMEM 896MB ~ 結(jié)束(1G)
高端內(nèi)存是指物理地址大于 896M 的內(nèi)存。對(duì)于這樣的內(nèi)存,無(wú)法在“內(nèi)核直接映射空間”進(jìn)行映射。
為什么?
因?yàn)椤皟?nèi)核直接映射空間”最多只能從 3G 到 4G,只能直接映射 1G 物理內(nèi)存,對(duì)于大于 1G 的物理內(nèi)存,無(wú)能為力。
高端內(nèi)存映射有三種方式:
1、映射到“內(nèi)核動(dòng)態(tài)映射空間”
這種方式很簡(jiǎn)單,因?yàn)橥ㄟ^(guò) vmalloc() ,在“內(nèi)核動(dòng)態(tài)映射空間”申請(qǐng)內(nèi)存的時(shí)候,就可能從高端內(nèi)存獲得頁(yè)面(參看 vmalloc 的實(shí)現(xiàn)),因此說(shuō)高端內(nèi)存有可能映射到“內(nèi)核動(dòng)態(tài)映射空間” 中。
2、永久內(nèi)核映射
如果是通過(guò) alloc_page() 獲得了高端內(nèi)存對(duì)應(yīng)的 page,如何給它找個(gè)線性空間?
內(nèi)核專(zhuān)門(mén)為此留出一塊線性空間,從 PKMAP_BASE 到 FIXADDR_START ,用于映射高端內(nèi)存。在 2.4 內(nèi)核上,這個(gè)地址范圍是 4G-8M 到 4G-4M 之間。這個(gè)空間起叫“內(nèi)核永久映射空間”或者“永久內(nèi)核映射空間”
這個(gè)空間和其它空間使用同樣的頁(yè)目錄表,對(duì)于內(nèi)核來(lái)說(shuō),就是 swapper_pg_dir,對(duì)普通進(jìn)程來(lái)說(shuō),通過(guò) CR3 寄存器指向。
通常情況下,這個(gè)空間是 4M 大小,因此僅僅需要一個(gè)頁(yè)表即可,內(nèi)核通過(guò)來(lái) pkmap_page_table 尋找這個(gè)頁(yè)表。
通過(guò) kmap(), 可以把一個(gè) page 映射到這個(gè)空間來(lái)
由于這個(gè)空間是 4M 大小,最多能同時(shí)映射 1024 個(gè) page。因此,對(duì)于不使用的的 page,應(yīng)該及時(shí)從這個(gè)空間釋放掉(也除映射關(guān)就是解系),通過(guò) kunmap() ,可以把一個(gè) page 對(duì)應(yīng)的線性地址從這個(gè)空間釋放出來(lái)。
3、臨時(shí)映射
內(nèi)核在 FIXADDR_START 到 FIXADDR_TOP 之間保留了一些線性空間用于特殊需求。這個(gè)空間稱(chēng)為“固定映射空間”
在這個(gè)空間中,有一部分用于高端內(nèi)存的臨時(shí)映射。
這塊空間具有如下特點(diǎn):
1、 每個(gè) CPU 占用一塊空間
2、 在每個(gè) CPU 占用的那塊空間中,又分為多個(gè)小空間,每個(gè)小空間大小是 1 個(gè) page,每個(gè)小空間用于一個(gè)目的,這些目的定義在 kmap_types.h 中的 km_type 中。
當(dāng)要進(jìn)行一次臨時(shí)映射的時(shí)候,需要指定映射的目的,根據(jù)映射目的,可以找到對(duì)應(yīng)的小空間,然后把這個(gè)空間的地址作為映射地址。這意味著一次臨時(shí)映射會(huì)導(dǎo)致以前的映射被覆蓋。
通過(guò) kmap_atomic() 可實(shí)現(xiàn)臨時(shí)映射。
下圖簡(jiǎn)單簡(jiǎn)單表達(dá)如何對(duì)高端內(nèi)存進(jìn)行映射
Linux內(nèi)存線性地址空間大小為4GB,分為2個(gè)部分:用戶空間部分(通常是3G)和內(nèi)核空間部分(通常是1G)。在此我們主要關(guān)注內(nèi)核地址空間部分。
內(nèi)核通過(guò)內(nèi)核頁(yè)全局目錄來(lái)管理所有的物理內(nèi)存,由于線性地址前3G空間為用戶使用,內(nèi)核頁(yè)全局目錄前768項(xiàng)(剛好3G)除0、1兩項(xiàng)外全部為0,后256項(xiàng)(1G)用來(lái)管理所有的物理內(nèi)存。內(nèi)核頁(yè)全局目錄在編譯時(shí)靜態(tài)地定義為swapper_pg_dir數(shù)組,該數(shù)組從物理內(nèi)存地址0x101000處開(kāi)始存放。
由圖可見(jiàn),內(nèi)核線性地址空間部分從PAGE_OFFSET(通常定義為3G)開(kāi)始,為了將內(nèi)核裝入內(nèi)存,從PAGE_OFFSET開(kāi)始8M線性地址用來(lái)映射內(nèi)核所在的物理內(nèi)存地址(也可以說(shuō)是內(nèi)核所在虛擬地址是從PAGE_OFFSET開(kāi)始的);接下來(lái)是mem_map數(shù)組,mem_map的起始線性地址與體系結(jié)構(gòu)相關(guān),比如對(duì)于UMA結(jié)構(gòu),由于從PAGE_OFFSET開(kāi)始16M線性地址空間對(duì)應(yīng)的16M物理地址空間是DMA區(qū),mem_map數(shù)組通常開(kāi)始于PAGE_OFFSET+16M的線性地址;從PAGE_OFFSET開(kāi)始到VMALLOC_START – VMALLOC_OFFSET的線性地址空間直接映射到物理內(nèi)存空間(一一對(duì)應(yīng)影射,物理地址<==>線性地址-PAGE_OFFSET),這段區(qū)域的大小和機(jī)器實(shí)際擁有的物理內(nèi)存大小有關(guān),這兒VMALLOC_OFFSET在X86上為8M,主要用來(lái)防止越界錯(cuò)誤;在內(nèi)存比較小的系統(tǒng)上,余下的線性地址空間(還要再減去空白區(qū)即VMALLOC_OFFSET)被vmalloc()函數(shù)用來(lái)把不連續(xù)的物理地址空間映射到連續(xù)的線性地址空間上,在內(nèi)存比較大的系統(tǒng)上,vmalloc()使用從VMALLOC_START到VMALLOC_END(也即PKMAP_BASE減去2頁(yè)的空白頁(yè)大小PAGE_SIZE(解釋VMALLOC_END))的線性地址空間,此時(shí)余下的線性地址空間(還要再減去2頁(yè)的空白區(qū)即VMALLOC_OFFSET)又可以分成2部分:第一部分從PKMAP_BASE到FIXADDR_START用來(lái)由kmap()函數(shù)來(lái)建立永久映射高端內(nèi)存;第二部分,從FIXADDR_START到FIXADDR_TOP,這是一個(gè)固定大小的臨時(shí)映射線性地址空間,(引用:Fixed virtual addresses are needed for subsystems that need to know the virtual address at compile time such as the APIC),在X86體系結(jié)構(gòu)上,F(xiàn)IXADDR_TOP被靜態(tài)定義為0xFFFFE000,此時(shí)這個(gè)固定大小空間結(jié)束于整個(gè)線性地址空間最后4K前面,該固定大小空間大小是在編譯時(shí)計(jì)算出來(lái)并存儲(chǔ)在__FIXADDR_SIZE變量中。
正是由于vmalloc()使用區(qū)、kmap()使用區(qū)及固定大小區(qū)(kmap_atomic()使用區(qū))的存在才使ZONE_NORMAL區(qū)大小受到限制,由于內(nèi)核在運(yùn)行時(shí)需要這些函數(shù),因此在線性地址空間中至少要VMALLOC_RESERVE大小的空間。VMALLOC_RESERVE的大小與體系結(jié)構(gòu)相關(guān),在X86上,VMALLOC_RESERVE定義為128M,這就是為什么ZONE_NORMAL大小通常是16M到896M的原因。
到此,相信大家對(duì)“如何理解Linux系統(tǒng)下的高端內(nèi)存”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
文章題目:如何理解Linux系統(tǒng)下的高端內(nèi)存
本文來(lái)源:http://www.rwnh.cn/article18/ippegp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、軟件開(kāi)發(fā)、面包屑導(dǎo)航、手機(jī)網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站建設(shè)、微信小程序
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)