內(nèi)核除了管理本身的內(nèi)存外阻肿,還必須管理用戶空間中進(jìn)程的內(nèi)存瓦戚,也就是進(jìn)程地址空間。
一丛塌、地址空間
進(jìn)程地址空間由進(jìn)程可尋址的虛擬內(nèi)存組成较解,內(nèi)核允許進(jìn)程使用這種虛擬內(nèi)存中的地址。每個(gè)進(jìn)程都有一個(gè)32或64位的平坦地址空間姨伤,取決于體系結(jié)構(gòu)哨坪。平坦是指地址空間范圍是一個(gè)獨(dú)立的連續(xù)區(qū)間庸疾。
內(nèi)存地址要在地址空間范圍之內(nèi)乍楚。地址空間中,可被進(jìn)程訪問打的合法地址空間稱為內(nèi)存區(qū)域届慈。通過內(nèi)核徒溪,進(jìn)程可以給自己的地址空間動(dòng)態(tài)增加或減少內(nèi)存區(qū)域。若進(jìn)程訪問了不在有效范圍中的內(nèi)存區(qū)域或以不正確的方式訪問了有效地址金顿,那么內(nèi)核就會(huì)終止該進(jìn)程臊泌,并返回“段錯(cuò)誤”信息。
內(nèi)存區(qū)域可以包含各種內(nèi)存對(duì)象:
- 可執(zhí)行文件代碼的內(nèi)存映射揍拆,稱為代碼段(text section)渠概;
- 可執(zhí)行文件的已初始化全局變量的內(nèi)存映射,稱為數(shù)據(jù)段(data section)嫂拴;
- 包含未初始化全局變量播揪,也就是bss段的零頁的內(nèi)存映射
- 用于進(jìn)程用戶空間棧的零頁的內(nèi)存映射
- 每一個(gè)諸如C庫或動(dòng)態(tài)鏈接程序等共享庫的代碼段、數(shù)據(jù)段和bss也會(huì)被載入進(jìn)程的地址空間筒狠;
- 任何內(nèi)存映射文件
- 任何共享內(nèi)存段
- 任何匿名的內(nèi)存映射
二猪狈、內(nèi)存描述符
內(nèi)核使用內(nèi)存描述符結(jié)構(gòu)體mm_struct表示進(jìn)程的地址空間。
該結(jié)構(gòu)體是進(jìn)程創(chuàng)建時(shí)通過allocate_mm宏分配的辩恼。若希望父進(jìn)程和子進(jìn)程共享地址空間雇庙,可以調(diào)用clone時(shí)設(shè)置CLONE_VM標(biāo)志,這樣的進(jìn)程稱為線程灶伊。內(nèi)存描述符通過exit_mm撤銷疆前。
三、虛擬內(nèi)存區(qū)域
內(nèi)存區(qū)域在Linux內(nèi)核中也稱作虛擬內(nèi)存區(qū)域(virtual memory Areas聘萨,VMAs) 竹椒。vm_area_struct結(jié)構(gòu)體描述了指定地址空間內(nèi)連續(xù)區(qū)間上的一個(gè)獨(dú)立內(nèi)存范圍。內(nèi)核將每個(gè)內(nèi)存區(qū)作為一個(gè)單獨(dú)的內(nèi)存對(duì)象管理匈挖,每個(gè)內(nèi)存區(qū)域都擁有一個(gè)一致的屬性碾牌,相應(yīng)的操作也一致康愤。
四、頁表
應(yīng)用程序訪問虛擬地址時(shí)舶吗,需要將其轉(zhuǎn)化為物理地址征冷,然后處理器才能解析地址訪問請(qǐng)求。地址轉(zhuǎn)化需要將虛擬地址分段誓琼,使每段虛擬地址都作為一個(gè)索引指向頁表检激,而頁表項(xiàng)則指向下一級(jí)別的頁表或指向最終的物理頁面。Linux使用三級(jí)頁表完成地址轉(zhuǎn)化:
- PGD:頂級(jí)頁表腹侣,頁全局目錄
- PMD:中間頁目錄
- PTE:頁表叔收,指向物理頁面
搜索內(nèi)存中的物理地址速度有限,為了加快搜索速度傲隶,多數(shù)體系結(jié)構(gòu)實(shí)現(xiàn)了翻譯后緩沖器(TLB)饺律,TLB作為一個(gè)將虛擬地址映射到物理地址的硬件緩存,當(dāng)請(qǐng)求訪問一個(gè)虛擬地址時(shí)跺株,處理器將首先檢查TLB中是否有對(duì)應(yīng)緩存复濒,如果命中則立刻返回物理地址;否則就需要通過頁表搜索物理地址乒省。