<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > linux下內(nèi)存管理學(xué)習(xí)心得(一)

          linux下內(nèi)存管理學(xué)習(xí)心得(一)

          作者: 時(shí)間:2016-11-23 來(lái)源:網(wǎng)絡(luò) 收藏
          最近在學(xué)習(xí)內(nèi)存管理的時(shí)候,發(fā)現(xiàn)對(duì)linux下的所謂內(nèi)存如何管理如何分配都不熟悉,通過(guò)最近的查閱資料可總結(jié)如下,如有不妥之處歡迎大家批評(píng)與指正。

          總的的來(lái)說(shuō)linux的內(nèi)存管理其實(shí)主要難理解的是以下幾個(gè)部分:

          本文引用地址:http://www.ex-cimer.com/article/201611/320404.htm

          1、虛擬地址、物理地址、線性地址、邏輯地址之間的區(qū)別。

          2、用戶(hù)地址空間與內(nèi)核地址空間區(qū)別。

          3、內(nèi)核如何分配所謂的地址。

          4、一個(gè)可執(zhí)行程序的地址分布以及運(yùn)行地址分配。

          目前我也大概總結(jié)這幾個(gè),其實(shí)這方面的知識(shí)肯定很多,但限于能力只能如何,也盡最大努力詳細(xì)分析其中原委。注:很多是參考了網(wǎng)上的大??偨Y(jié)的。

          一、各地址之間區(qū)別

          1、虛擬地址

          其中各種地址的概念大家都可查閱到,我也就不多說(shuō)了,虛擬地址就是為了給用戶(hù)一個(gè)更大的使用空間(當(dāng)然這個(gè)使用空間肯定是虛擬了的),然后32位下面用戶(hù)地址空間也就是虛擬地址空間范圍就是0--4GB。其中這個(gè)范圍又可以劃為0--3GB-1用戶(hù)空間和3GB--4GB-1的內(nèi)核空間。其中進(jìn)程都各自有各自的0--3GB-1地址范圍而共享3GB--4GB-1的內(nèi)核空間。更詳細(xì)的請(qǐng)往下此處不講為了大家先有個(gè)宏觀的認(rèn)識(shí)。

          1、分頁(yè)單元中,頁(yè)目錄的地址放在CUP的CR3寄存器中,是進(jìn)行抵制轉(zhuǎn)換的開(kāi)始點(diǎn)。

          2、每個(gè)進(jìn)程,都有其獨(dú)立的虛擬地址空間,運(yùn)行一個(gè)進(jìn)程,首先需要將它的頁(yè)目錄地址放在CR3寄存器中,其他的進(jìn)程的保存下來(lái)。

          3、每一個(gè)32位的線性地址被劃分為三部分:頁(yè)目錄索引(10位):頁(yè)表索引(10位):偏移12位。

          裝換:

          1、先裝入進(jìn)程的頁(yè)目錄地址(調(diào)度程序把這個(gè)地址裝入CR3中);

          2、根據(jù)線性地址前10位,在頁(yè)目錄中找到對(duì)應(yīng)的索引項(xiàng),頁(yè)目錄中的項(xiàng)是一個(gè)頁(yè)表的地址;

          3、根據(jù)線性地址的中間10位,在頁(yè)表中找到頁(yè)的起始地址;

          4、將頁(yè)的起始地址與線性地址的最后12為偏移地址相加最后為物理地址。

          二、用戶(hù)地址與內(nèi)核地址

          Linux 操作系統(tǒng)和驅(qū)動(dòng)程序運(yùn)行在內(nèi)核空間,應(yīng)用程序運(yùn)行在用戶(hù)空間,兩者不能簡(jiǎn)單地使用指針傳遞數(shù)據(jù),因?yàn)長(zhǎng)inux使用的虛擬內(nèi)存機(jī)制,用戶(hù)空間的數(shù)據(jù)可能被換出,當(dāng)內(nèi)核空間使用用戶(hù)空間指針時(shí),對(duì)應(yīng)的數(shù)據(jù)可能不在內(nèi)存中。

          其中內(nèi)核地址空間是由內(nèi)核負(fù)責(zé)映射,它并不會(huì)跟著進(jìn)程改變,是固定的。其中內(nèi)核空間分布如下:

          (1)直接內(nèi)存映射區(qū)

          從3G開(kāi)始,最大896M的線性地址區(qū)間,我們稱(chēng)作直接內(nèi)存映射區(qū),這是因?yàn)樵搮^(qū)域的線性地址和物理地址之間存在線性裝換關(guān)系:線性地址=3G+物理地址

          (2)動(dòng)態(tài)內(nèi)存映射區(qū)

          又內(nèi)核函數(shù)vmalloc來(lái)進(jìn)行分配,其特點(diǎn)是線性空間連續(xù),但物理地址空間不一定連續(xù)。

          (3)永久內(nèi)存映射區(qū)

          使用kmap函數(shù)將分配到得896M以上的高端內(nèi)存映射到該區(qū)

          (4)固定映射區(qū)

          特殊用途

          用戶(hù)空間

          用戶(hù)空間是0-3GB-1的空間范圍。這里就提前說(shuō)一下程序鏡像加載到運(yùn)行的過(guò)程。

          首先二進(jìn)制程序是放在外部存儲(chǔ)器中的,當(dāng)啟動(dòng)一個(gè)進(jìn)程的時(shí)候先分配自己進(jìn)程的虛擬空間,這個(gè)時(shí)候?qū)⒊绦蜱R像加載到內(nèi)存(具體內(nèi)核過(guò)程下面介紹),如何鏡像很大的話先加載一部分(這部分是多大?我還不清楚有待研究),然后這個(gè)時(shí)候進(jìn)程的空間就會(huì)映射(一定注意是映射,因?yàn)楦揪蜎](méi)有這樣的地址,這只是個(gè)虛的),此時(shí)該進(jìn)程好像有了這個(gè)鏡像了,那么進(jìn)程執(zhí)行的時(shí)候根據(jù)線性地址找到物理地址(內(nèi)存)中的代碼執(zhí)行。就是這么簡(jiǎn)單。

          三、內(nèi)核分配內(nèi)存

          在linux操作系統(tǒng)中,每個(gè)進(jìn)程都通過(guò)一個(gè)task_struct的結(jié)構(gòu)體描敘,每個(gè)進(jìn)程的地址空間都通過(guò)一個(gè)mm_struct描敘,c語(yǔ)言中的每個(gè)段空間都通過(guò)vm_area_struct表示,他們關(guān)系如下 :

            當(dāng)運(yùn)行一個(gè)程序時(shí),操作系統(tǒng)需要?jiǎng)?chuàng)建一個(gè)進(jìn)程,這個(gè)進(jìn)程和程序之間都干了些什么呢?

            當(dāng)一個(gè)程序被執(zhí)行時(shí),該程序的內(nèi)容必須被放到進(jìn)程的虛擬地址空間,對(duì)于可執(zhí)行程序的共享庫(kù)也是如此??蓤?zhí)行程序并非真正讀到物理內(nèi)存中,而只是鏈接到進(jìn)程的虛擬內(nèi)存中。

            當(dāng)一個(gè)可執(zhí)行程序映射到進(jìn)程虛擬地址空間時(shí),一組vm_area_struct數(shù)據(jù)結(jié)構(gòu)將被產(chǎn)生。每個(gè)vm_area_struct數(shù)據(jù)結(jié)構(gòu)表示可執(zhí)行印象的一部分;是可執(zhí)行代碼,或是初始化的數(shù)據(jù),以及未初始化的數(shù)據(jù)等。

            linux操作系統(tǒng)是通過(guò)sys_exec對(duì)可執(zhí)行文件進(jìn)行映射以及讀取的,有如下幾步:

            1.創(chuàng)建一組vm_area_struct

            2.圈定一個(gè)虛擬用戶(hù)空間,將其起始結(jié)束地址(elf段中已設(shè)置好)保存到vm_start和vm_end中。

            3.將磁盤(pán)file句柄保存在vm_file中

            4.將對(duì)應(yīng)段在磁盤(pán)file中的偏移值(elf段中已設(shè)置好)保存在vm_pgoff中;

            5.將操作該磁盤(pán)file的磁盤(pán)操作函數(shù)保存在vm_ops中

            注意:這里沒(méi)有對(duì)應(yīng) 的頁(yè)目錄表項(xiàng)創(chuàng)建頁(yè)表,更不存在設(shè)置頁(yè)表項(xiàng)了。

            假設(shè)現(xiàn)在程序中有一條指令需要讀取上面vm_start--vm_end之間的某內(nèi)容

            例如:mov [0x08000011],%eax,那么將會(huì)執(zhí)行如下序列:

            1.cpu依據(jù)CR3(current->pgd)找到0x08000011地址對(duì)應(yīng)的pgd[i],由于該pgd[i]內(nèi)容保持為初始化狀態(tài)即為0,導(dǎo)致cpu異常.

            2.do_page_fault被調(diào)用,在該函數(shù)中,為pgd[i]在內(nèi)存中分配一個(gè)頁(yè)表,并讓該表項(xiàng)指向它,如下圖所示:

            注意:這里i為0x08000011高10位,j為其中間10位,此時(shí)pt表項(xiàng)全部為0(pte[j]也為0);

            3.為pte[j]分配一個(gè)真正的物理內(nèi)存頁(yè)面,依據(jù)vm_area_struct中的vm_file、vm_pgoff和vm_ops,調(diào)用filemap_nopage將磁盤(pán)file中vm_pgoff偏移處的內(nèi)容讀入到該物理頁(yè)面中,如下圖所示:

           ?、佟7峙湮锢韮?nèi)存頁(yè)面;

            ②。從磁盤(pán)文件中將內(nèi)容讀取到物理內(nèi)存頁(yè)面中

            從上面我們可以知道,在進(jìn)程創(chuàng)建的過(guò)程中,程序內(nèi)容被映射到進(jìn)程的虛擬內(nèi)存空間,為了讓一個(gè)很大的程序在有限的物理內(nèi)存空間運(yùn)行,我們可以把這個(gè)程序的開(kāi)始部分先加載到物理內(nèi)存空間運(yùn)行,因?yàn)椴僮飨到y(tǒng)處理的是進(jìn)程的虛擬地址,如果在進(jìn)行虛擬到物理地址的轉(zhuǎn)換工程中,發(fā)現(xiàn)物理地址不存在時(shí),這個(gè)時(shí)候就會(huì)發(fā)生缺頁(yè)異常(nopage),接著操作系統(tǒng)就會(huì)把磁盤(pán)上還沒(méi)有加載到內(nèi)存中的數(shù)據(jù)加載到物理內(nèi)存中,對(duì)應(yīng)的進(jìn)程頁(yè)表進(jìn)行更新。也許你會(huì)問(wèn),如果此時(shí)物理內(nèi)存滿(mǎn)了,操作系統(tǒng)將如何處理?

            下面我們看看linux操作系統(tǒng)是如何處理的:

            如果一個(gè)進(jìn)程想將一個(gè)虛擬頁(yè)裝入物理內(nèi)存,而又沒(méi)有可使用的空閑物理頁(yè),操作系統(tǒng)就必須淘汰物理內(nèi)存中的其他頁(yè)來(lái)為此頁(yè)騰出空間。

            在linux操作系統(tǒng)中,物理頁(yè)的描敘如下:

            struct mem_map

            {

            1.本頁(yè)使用計(jì)數(shù),當(dāng)該頁(yè)被許多進(jìn)程共享時(shí)計(jì)數(shù)將大于1.

            2.age描敘本頁(yè)的年齡,用來(lái)判斷該頁(yè)是否為淘汰或交換的好候選

            3.map_nr描敘物理頁(yè)的頁(yè)幀號(hào)

            }

            如果從物理內(nèi)存中被淘汰的頁(yè)來(lái)自于一個(gè)映像或數(shù)據(jù)文件,并且還沒(méi)有被寫(xiě)過(guò),則該頁(yè)不必保存,它可以丟掉。如果有進(jìn)程在需要該頁(yè)時(shí)就可以把它從映像或數(shù)據(jù)文件中取回內(nèi)存。


          上一頁(yè) 1 2 下一頁(yè)

          關(guān)鍵詞: linux內(nèi)存管理學(xué)習(xí)心

          評(píng)論


          相關(guān)推薦

          技術(shù)專(zhuān)區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();