新聞中心
作為開源領域更受歡迎的操作系統(tǒng)之一,Linux內(nèi)核已經(jīng)成為眾多IT從業(yè)者和開發(fā)者的首選選擇。其中,頁表是Linux內(nèi)核中處理內(nèi)存管理的核心部分之一。Linux內(nèi)核中的頁表可以根據(jù)虛擬地址獲取對應的物理地址,這個過程中牽涉到分頁、地址轉(zhuǎn)換等操作。那么,本文將深入探討,以及其中涉及的相關操作。

創(chuàng)新互聯(lián)2013年開創(chuàng)至今,是專業(yè)互聯(lián)網(wǎng)技術服務公司,擁有項目成都網(wǎng)站建設、網(wǎng)站設計網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元溫州做網(wǎng)站,已為上家服務,為溫州各地企業(yè)和個人服務,聯(lián)系電話:18980820575
一、頁表是什么?
在計算機中,內(nèi)存被劃分為很多固定大小的塊,成為”頁面”(Page)。每個頁面的大小通常為4KB,也就是說,每個頁面可以存儲4*1024個字節(jié)的數(shù)據(jù)。計算機中的程序在運行時,需要加載到內(nèi)存中才能執(zhí)行。以C語言編寫的程序,編譯成可執(zhí)行文件后,為了方便加載和管理,內(nèi)存中的數(shù)據(jù)和代碼會被分割成若干個固定大小的塊,每個塊就是一個頁面。
頁面不是獨立存在的,而是需要組成一個頁表。頁表是一種數(shù)據(jù)結(jié)構,能夠?qū)⑻摂M地址映射成物理地址。虛擬地址是程序使用的地址,而物理地址是實際存儲數(shù)據(jù)的地址。當程序需要訪問內(nèi)存中的數(shù)據(jù)時,Linux內(nèi)核將根據(jù)虛擬地址檢索頁表,從而找到對應的物理地址。因此,頁表是指內(nèi)核中一種數(shù)據(jù)結(jié)構,其中存儲了虛擬地址與物理地址的映射關系,方便程序在內(nèi)存中讀取和存儲數(shù)據(jù)。
二、Linux內(nèi)核中如何創(chuàng)建頁表?
在Linux中,內(nèi)核負責管理內(nèi)存分配和釋放,而創(chuàng)建頁表就是其中必不可少的操作之一。下面將從分頁機制、地址轉(zhuǎn)換等角度,深入探討。
(一)分頁機制
Linux內(nèi)核采用的是分頁機制,將物理內(nèi)存劃分成固定大小的塊,即頁面,其大小為4KB。為了方便管理,由內(nèi)核進行管理,其中包括將每個頁面與一個頁框?qū)饋?。頁框是物理?nèi)存中的一個固定大小的塊,其大小與頁面相同,有一個長度為32位的標識符。當程序需要從內(nèi)存中讀取數(shù)據(jù)時,Linux內(nèi)核根據(jù)頁面的大小將數(shù)據(jù)劃分成多個頁面,然后將這些頁面映射到物理地址中去。這樣就可以更好地利用物理內(nèi)存。
(二)地址轉(zhuǎn)換
Linux內(nèi)核中創(chuàng)建頁表還涉及到地址轉(zhuǎn)換的操作。在Linux中,計算機分配給每個進程的虛擬地址空間是相同的,而不同進程之間的虛擬地址是不同的。進程在執(zhí)行過程中,就是將自己的虛擬地址空間映射到物理地址空間中去。操作系統(tǒng)管理著一張全局的頁表,每次進程發(fā)生虛擬地址轉(zhuǎn)換時,都需要在這張頁表中查找對應的物理地址映射。
地址轉(zhuǎn)換的過程如下:
1、16位的段選擇符,選擇要使用的段描述符。
2、根據(jù)段描述符的內(nèi)容找到段的基址(段基址+偏移量,最終形成一個32位的虛擬地址)。
3、將虛擬地址中的高10位(前22位)作為索引,找到頁目錄表中對應項的地址。
4、用虛擬地址中間10位(位于22到31的位置)作為索引,找到頁表中對應的頁表條目。
5、使用虛擬地址的最后12位(位于0到11)作為索引,找到頁表條目的對應頁面,將其物理地址返回。
(三)物理、邏輯地址空間劃分
Linux中將物理內(nèi)存分成3個區(qū)域,即內(nèi)核空間、DMA空間以及進程地址空間。其中,內(nèi)核空間中包含的內(nèi)存劃分給內(nèi)核使用,DMA空間提供訪問設備的內(nèi)存地址,進程地址空間為用戶進程提供的內(nèi)存空間。物理內(nèi)存區(qū)間的具體劃分如下:
1、00000000 – 9fffffff:用戶空間,內(nèi)存地址從 0 開始。
2、a0000000 – bfffffff:內(nèi)核 I/O 映射空間,預留了一段虛擬地址區(qū)域,對應物理地址的范圍是 a0000000 到 bfffffff。這段區(qū)域的內(nèi)存訪問不通過 TLB。映射關系通過 ioremap 函數(shù)建立。ioremap_nocache 用于不能被 CPU cache 映射的區(qū)域。除了CPU之外,沒有任何硬件會通過訪問這個區(qū)域獲取信息。
3、c0000000 – c03fffff:內(nèi)核虛擬地址空間,即內(nèi)核代碼,全局變量等。從此處開始的區(qū)間是內(nèi)核的虛擬地址空間,內(nèi)核的代碼、全局數(shù)據(jù)以及內(nèi)核映射的一些設備內(nèi)存等都位于這個地址空間內(nèi)。由于內(nèi)核可以訪問物理內(nèi)存,所以內(nèi)核也可以從物理地址空間中查找和管理內(nèi)存。簡單下來,內(nèi)核虛擬地址空間給內(nèi)核使用,且內(nèi)核和進程地址空間是隔離的。
(四)頁表管理
頁表是對程序虛擬地址和物理地址之間互相映射關系的描述,為了管理這些映射關系,Linux內(nèi)核需要建立頁目錄表和頁表。頁目錄表是一種存放頁表條目指針的數(shù)據(jù)結(jié)構,頁表條目包含了虛擬地址與物理地址之間的映射關系。
Linux中頁目錄表對應的數(shù)據(jù)結(jié)構為pgd_t,頁表條目對應的數(shù)據(jù)結(jié)構為pte_t。Linux內(nèi)核進行頁表的創(chuàng)建是在初始化內(nèi)存管理時完成的,在這個過程中,內(nèi)核會創(chuàng)建一張全局的也到表,用于記錄分配給每個進程的虛擬地址空間。同時,內(nèi)核中還會維護一組 FREE_PAGE 內(nèi)存池,用于申請和釋放頁面。申請頁面的函數(shù)名是get_free_page,而釋放頁面的函數(shù)名是put_page。
三、
通過以上的介紹,我們可以了解到Linux內(nèi)核中如何創(chuàng)建頁表。內(nèi)核采用了分頁機制,在頁面和頁框之間進行映射,同時,頁表也由頁目錄表和頁表條目組成。當進程需要訪問內(nèi)存中的數(shù)據(jù)時,內(nèi)核會在頁表中查找虛擬地址對應的物理地址,根據(jù)映射關系獲取對應數(shù)據(jù)。Linux內(nèi)核管理內(nèi)存,不僅能夠更好地利用系統(tǒng)資源,同時也很好地保證了程序的安全性和穩(wěn)定性。
相關問題拓展閱讀:
- 嵌入式中l(wèi)inux內(nèi)核在內(nèi)存中運行地址0x到內(nèi)存起始運行地址0x中的(0x8000=32k)怎么回事?
- Linux進程內(nèi)存如何管理?
嵌入式中l(wèi)inux內(nèi)核在內(nèi)存中運行地址0x到內(nèi)存起始運行地址0x中的(0x8000=32k)怎么回事?
/* 創(chuàng)建核心頁表 */
bl __create_page_tables
Linux進程內(nèi)存如何管理?
Linux內(nèi)存管理
摘要:本章首先以應用程序開發(fā)者的角度審視Linux的進程內(nèi)存管理,在此基礎上逐步深入到內(nèi)核中討論系統(tǒng)物理內(nèi)存管理和內(nèi)核內(nèi)存的使用方法。力求從外到內(nèi)、水到渠成地引導網(wǎng)友分析Linux的內(nèi)存管理與使用。在本章最后,我們給出一個內(nèi)存映射的實例,幫助網(wǎng)友們理解內(nèi)核內(nèi)存管理與用戶內(nèi)存管理之間的關系,希望大家最終能駕馭Linux內(nèi)存管理。
前言
內(nèi)存管理一向是所有操作系統(tǒng)書籍不惜筆墨重點討論的內(nèi)容,無論市面上或是網(wǎng)上都充斥著大量涉及內(nèi)存管理的教材和資料。因此,我們這里所要寫的Linux內(nèi)存管理采取避重就輕的策略,從橋弊理論層面就不去班門弄斧,貽笑大方了。我們最想做的和可能做到的是從開發(fā)者的角度談談對內(nèi)存管理的理解,最終目的是把我們在內(nèi)核開發(fā)中使用內(nèi)存的經(jīng)驗和對Linux內(nèi)存管理的認識與大家共享。
當然,這其中我們也會涉及到一些諸如段頁等內(nèi)存管理的基本理論,但我們的目的不是為了強調(diào)理論,而是為了指導理解開發(fā)中的實踐,橘消螞所以僅僅點到為止,不做深究。
遵循“理論來源于實踐”的“教條”,我們先不必一下子就鉆入內(nèi)核里去看系統(tǒng)內(nèi)存到底是如何管理,那樣往往會讓你陷入似懂非懂的窘境(我當年就犯了這個錯誤?。?。所以更好的方式是先從外部(用戶編程范疇)來觀察進程如何使用內(nèi)存,等到大家對內(nèi)存的使用有了較直觀的認識后,再深入到內(nèi)核中去學習內(nèi)存如何被管理等理論知識。最后再通過一個實例編程將所講內(nèi)容融會貫通。
進程與內(nèi)存
進程如何使用內(nèi)存?
毫無疑問,所有進程(執(zhí)行的程序)都必須占用一定數(shù)量的內(nèi)存,它或是用來存放從磁盤載入的程序代碼,或是存放取自用戶輸入的數(shù)據(jù)等等。不過進程對這些內(nèi)存的管理方式因內(nèi)存用途不一而不盡相同,有些內(nèi)存是事先靜態(tài)分配和統(tǒng)一回收的,而有些卻是按需要動態(tài)分配和回收的。
對任何一個普通進程來講,它都會涉及到5種不同的數(shù)據(jù)段。稍有編程知識的朋友都能想到這幾個數(shù)據(jù)段中包含有“程序代碼段”、“程序數(shù)據(jù)段”、“程序堆棧段”等。不錯,這幾種數(shù)據(jù)段都在其中,但除了以上幾種數(shù)據(jù)段之外,進程還另外包含兩種數(shù)據(jù)段。下面我們來簡單歸納一下進程對應的內(nèi)存空間中所包含的5種不同的數(shù)據(jù)區(qū)。
*代碼段*:代碼段是用來存放可執(zhí)行文件的操作指令,也就是說是它是可執(zhí)行程序在內(nèi)存中的鏡像。代碼段需要防止在運行時被非法修改,所以只準許讀取操作,而不允許寫入(修改)操作——它是不可寫的。
*數(shù)據(jù)段*:數(shù)據(jù)段用來存放可執(zhí)行文件中已初始化圓埋全局變量,換句話說就是存放程序靜態(tài)分配的變量和全局變量。
BSS*段***:BSS段包含了程序中未初始化的全局變量,在內(nèi)存中 bss段全部置零。
堆(heap*)*:堆是用于存放進程運行中被動態(tài)分配的內(nèi)存段,它的大小并不固定,可動態(tài)擴張或縮減。當進程調(diào)用malloc等函數(shù)分配內(nèi)存時,新分配的內(nèi)存就被動態(tài)添加到堆上(堆被擴張);當利用free等函數(shù)釋放內(nèi)存時,被釋放的內(nèi)存從堆中被剔除(堆被縮減)
*棧*:棧是用戶存放程序臨時創(chuàng)建的局部變量,也就是說我們函數(shù)括弧“{}”中定義的變量(但不包括static聲明的變量,static意味著在數(shù)據(jù)段中存放變量)。除此以外,在函數(shù)被調(diào)用時,其參數(shù)也會被壓入發(fā)起調(diào)用的進程棧中,并且待到調(diào)用結(jié)束后,函數(shù)的返回值也會被存放回棧中。由于棧的先進先出特點,所以棧特別方便用來保存/恢復調(diào)用現(xiàn)場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數(shù)據(jù)的內(nèi)存區(qū)。
進程如何組織這些區(qū)域?
上述幾種內(nèi)存區(qū)域中數(shù)據(jù)段、BSS和堆通常是被連續(xù)存儲的——內(nèi)存位置上是連續(xù)的,而代碼段和棧往往會被獨立存放。有趣的是,堆和棧兩個區(qū)域關系很“曖昧”,他們一個向下“長”(i386體系結(jié)構中棧向下、堆向上),一個向上“長”,相對而生。但你不必擔心他們會碰頭,因為他們之間間隔很大(到底大到多少,你可以從下面的例子程序計算一下),絕少有機會能碰到一起。
Linux系統(tǒng)提供了復雜的存儲管理系統(tǒng),使得進程所能訪問的內(nèi)存達到4GB。在Linux系統(tǒng)中,進程的4GB內(nèi)存空滑物間被分為兩個部分—顫讓掘—用戶空間與內(nèi)核空間。用戶空間的地址一般分布為0~3GB(即PAGE_OFFSET,在Ox86中它等于OxC),這樣,剩下的3~4GB為內(nèi)核空間,用戶進程通常只能訪問用戶空間的虛擬地址,不能訪問內(nèi)核空間的虛擬地址。用戶進程只有通過系統(tǒng)調(diào)用(代表用戶進程在內(nèi)核態(tài)執(zhí)行)等方式才可以訪問到內(nèi)核空間。每個進程的用戶空間都是完全獨立、互不相干的,用戶進程各自有不同的頁表。而內(nèi)核空間是由內(nèi)核負責映射,它并不會跟著進程改變,是固定的。內(nèi)核空間的虛擬地址到物理地址映射是被所有進程共享的,內(nèi)核的虛擬空間獨立于其他程序。Linux中1GB的內(nèi)核地址空間又被劃分為物理內(nèi)存映射區(qū)、虛擬內(nèi)存分配區(qū)、高端頁面映射區(qū)、專用頁面映射區(qū)和系統(tǒng)保留映射區(qū)這幾個區(qū)域。對于x86系統(tǒng)而言,一般情況下,物理內(nèi)存映射區(qū)更大長度為896MB,系統(tǒng)的物理內(nèi)存被順序映射在內(nèi)核空間的這個區(qū)域中。當系統(tǒng)物理內(nèi)存大于896MB時,超過物理內(nèi)存映射區(qū)的那部分內(nèi)存稱為高端內(nèi)存(而未超過物理內(nèi)存映射區(qū)的內(nèi)存通常被稱為常規(guī)內(nèi)存),內(nèi)核在存取高端內(nèi)存時必須將它們映射到高端頁面映射區(qū)。Linux保留內(nèi)核空間最頂部FIXADDR_TOP~4GB的區(qū)域作為保留區(qū)。當系統(tǒng)物理內(nèi)存超過4GB時,必須使用CPU的擴展分頁(PAE)模式所提供的64位頁目錄項才能存取到4GB以上的物理內(nèi)存,這需要CPU的支持。加入了PAE功能的Intel Pentium Pro及以后的CPU允許內(nèi)存更大可配置到64GB,它們茄核具備36位物理地址空間尋址能力。由此可見,對于32位的x86而言,在3~4GB之間的內(nèi)核空間中,從低地址到高地址依次為:物理內(nèi)存映射區(qū)隔離帶vmalloc虛擬內(nèi)存分配器區(qū)隔離帶高端內(nèi)存映射區(qū)專用頁面映射區(qū)保留區(qū)。
這個不是1-2句仔液粗話就表達明白的??梢钥聪挛覍懙南嚓P書籍。
第9章 Linux進程管理命令 / 298
9.1ps:查看進程 / 298
9.2pstree:顯示進程狀態(tài)樹 / 305
9.3pgrep:查找匹配條件的進程 / 306
9.4kill:終止進程 / 307
9.5killall:通過進程名終止進程 / 310
9.6pkill:通過進程名終止進程 / 311
9.7top:實時顯示系統(tǒng)中各個進程的資源占用狀況 / 313
9.8nice:調(diào)整程序運行時的優(yōu)先級 / 320
9.9renice:調(diào)整運行中的進程的優(yōu)先級 / 323
9.10nohup:用戶退出系統(tǒng)進程埋帶繼續(xù)工作 / 324
9.11strace:跟蹤進程的系統(tǒng)調(diào)用 / 325
9.12ltrace:跟蹤進程調(diào)用庫念鎮(zhèn)函數(shù) / 332
9.13runlevel:輸出當前運行級別 / 334
9.14init:初始化Linux進程 / 335
關于linux 內(nèi)核頁表創(chuàng)建的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關注本站。
成都網(wǎng)站營銷推廣找創(chuàng)新互聯(lián),全國分站站群網(wǎng)站搭建更好做SEO營銷。
創(chuàng)新互聯(lián)(www.cdcxhl.com)四川成都IDC基礎服務商,價格厚道。提供成都服務器托管租用、綿陽服務器租用托管、重慶服務器托管租用、貴陽服務器機房服務器托管租用。
名稱欄目:Linux內(nèi)核如何創(chuàng)建頁表 (linux 內(nèi)核頁表創(chuàng)建)
URL地址:http://fisionsoft.com.cn/article/cogcchc.html


咨詢
建站咨詢
