久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

LINUX程序的虛擬內(nèi)存映射機(jī)制

 clhon 2011-04-12
1)虛擬內(nèi)存的解釋:

虛擬內(nèi)存的核心概念是指代碼所用的內(nèi)存地址與物理地址沒有關(guān)系.
在用戶空間中,一個(gè)進(jìn)程的虛擬地址A指向不同的物理內(nèi)存,而不是另一個(gè)進(jìn)程的地址A.
任何時(shí)候CPU發(fā)送指令向內(nèi)存存取數(shù)據(jù)時(shí),通過軟件將虛擬地址的數(shù)據(jù)變?yōu)槲锢淼刂?
將虛擬地址變?yōu)槲锢淼刂纷優(yōu)槲锢淼刂返墓ぷ魇怯蓛?nèi)存管理單元(MMU)完成的.
虛擬內(nèi)存地址也可以稱為邏輯地址.

2)內(nèi)存管理單元:

內(nèi)存管理單元是CPU功能的一部份,如果CPU有cache,它將有一個(gè)內(nèi)存管理單元,反之亦然.
內(nèi)存管理單元可以將兩個(gè)進(jìn)程對(duì)同一內(nèi)存邏輯地址的訪問映射到不同的物理地址.
內(nèi)存管理單元同高速緩存密切協(xié)作,在RAM和高速緩存之間按要求傳遞內(nèi)存.
內(nèi)存管理單元將內(nèi)存分成許多頁,它是可利用物理內(nèi)存的最小單位,每頁包含4KB字節(jié)的地址空間.

3)虛擬內(nèi)存到物理內(nèi)存的映射:


3.1)映射的過程:

虛擬地址到物理地址的轉(zhuǎn)化是與體系結(jié)構(gòu)相關(guān)的,在X86 CPU上是以分段,分頁兩種方式轉(zhuǎn)化的.

虛擬地址(邏輯地址)---段式映射---線性地址---頁式映射---物理地址

Linux采用段頁式管理方式是由于intel的X86 CPU的硬件體系結(jié)構(gòu)決定的.這樣的雙重映射本身毫無必要,在Linux中段式映射不起什么作用.
可以理解為虛擬地址就是線性地址.
通過以下的程序來分析虛擬內(nèi)存到線性地址再到物理內(nèi)存的映射,我們還以X86為例:


vi hello.c

#include <stdio.h>

int greeting(){
        printf("Hello world!\n");
        return 0;
}

int
main (){
        greeting();
        return 0;
}

編寫一個(gè)HELLO WORLD程序,用gcc hello.c -o hello編譯


objdump -xd hello

這里我們主要看main和greeting的調(diào)用:
08048354 <greeting>:
 8048354:       55                      push   %ebp
 8048355:       89 e5                   mov    %esp,%ebp
 8048357:       83 ec 08                sub    $0x8,%esp
 804835a:       c7 04 24 70 84 04 08    movl   $0x8048470,(%esp)
 8048361:       e8 2e ff ff ff          call   8048294 <puts@plt>
 8048366:       b8 00 00 00 00          mov    $0x0,%eax
 804836b:       c9                      leave  
 804836c:       c3                      ret    

0804836d <main>:
 804836d:       8d 4c 24 04             lea    0x4(%esp),%ecx
 8048371:       83 e4 f0                and    $0xfffffff0,%esp
 8048374:       ff 71 fc                pushl  0xfffffffc(%ecx)
 8048377:       55                      push   %ebp
 8048378:       89 e5                   mov    %esp,%ebp
 804837a:       51                      push   %ecx
 804837b:       83 ec 04                sub    $0x4,%esp
 804837e:       e8 d1 ff ff ff          call   8048354 <greeting>
 8048383:       b8 00 00 00 00          mov    $0x0,%eax
 8048388:       83 c4 04                add    $0x4,%esp
 804838b:       59                      pop    %ecx
 804838c:       5d                      pop    %ebp
 804838d:       8d 61 fc                lea    0xfffffffc(%ecx),%esp
 8048390:       c3                      ret    
 
 函數(shù)main()通過call   8048354 <greeting>調(diào)用了greeting函數(shù).
 
首先可以看到ld給greeting分配的地址是0x08048354,在elf格式的可執(zhí)行代碼中,ld總是從0x08000000開始安排代碼段,對(duì)每個(gè)程序都這樣.
而程序在執(zhí)行時(shí)在物理內(nèi)存中的實(shí)際位置就要由內(nèi)核在為其建立內(nèi)存映射時(shí)臨時(shí)作出安排,具體地址則取決于當(dāng)時(shí)所分配的物理內(nèi)存頁面.這對(duì)于我們完全是透明的.
映射機(jī)制在程序運(yùn)行時(shí)就已經(jīng)建立起來了.


3.2)段式映射

從上例中,調(diào)用greeting()函數(shù)時(shí),當(dāng)前的地址是0x08048354,也就是EIP指針寄存器的值,那么CS的值是什么呢?
CS寄存器存放的是段式映射的選擇碼,可以理解為這是一個(gè)索引.
在LINUX中,選擇碼只有4個(gè),也就是說只可能是以下4個(gè)其中1個(gè),這4個(gè)選擇碼分別是:
段寄存器類型  數(shù)值  索引            TI  RPL   
__KERNEL_CS   0x10  0000 0000 00010 0   00
__KERNEL_DS   0x18  0000 0000 00011 0   00
__USER_CS     0x23  0000 0000 00100 0   11
__USER_DS     0x2B 0000 0000 00101 0   11

與上面的對(duì)照: 
__KERNEL_CS   index=2   TI=0   RPL=0
__KERNEL_DS   index=3   TI=0   RPL=0
__USER_CS     index=4   TI=0   RPL=3
__USER_DS     index=5   TI=0   RPL=3

對(duì)選擇碼進(jìn)行解釋說明:
1)關(guān)于段寄存器的賦值,依據(jù)以下的原則:
CS=__USER_CS
DS=__USER_DS
ES=__USER_DS
SS=__USER_DS
因?yàn)槲覀兊某绦蛟谟脩艨臻g中運(yùn)行,所以無論是代碼段還是數(shù)據(jù)段都是__USER_XX

2)關(guān)于TI的值,TI可以是GDT(全局段描述表),也可以是LDT(局部段描述表).
GDT對(duì)映的是0
LDT對(duì)映的是1
LINUX的TI幾乎都是0,LINUX內(nèi)核中基本上不使用局部描述表LDT,LDT只是在vm86模式中運(yùn)行wine以及其它在linux上模擬運(yùn)行windows
或DOS軟件的程序中才使用.

3)關(guān)于RPL,LINUX只用了0,3兩種級(jí)別.
0代表內(nèi)核進(jìn)程,3代表用戶進(jìn)程.

通過以上的分析,我們的程序顯然是用戶進(jìn)程,所以對(duì)映的就是__USER_CS,
最后CS寄存器的值就是0x23,而索引就是4.二進(jìn)制(100)=十進(jìn)制(4)

而在GDT全局描述表中4對(duì)映的是什么呢?
我們先來看看gdt全局描述表:

ENTRY(gdt_table)
 .quad  0x0000000000000000 /*NULL desccriptor*/
 .quad  0x0000000000000000 /*not used*/
 .quad  0x00cf9a000000ffff /*0x10 kernel 4GB code at 0x00000000*/
 .quad  0x00cf92000000ffff /*0x18 kernel 4GB code at 0x00000000*/
 .quad  0x00cffa000000ffff /*0x23 user 4GB code at 0x00000000*/
 .quad  0x00cff2000000ffff /*0x2b user 4GB code at 0x00000000*/
 .quad  0x0000000000000000 /*not used*/
 .quad  0x0000000000000000 /*not used*/

可以看到索引為4的GDT就是 
.quad  0x00cffa000000ffff /*0x23 user 4GB code at 0x00000000*/

現(xiàn)在把這4項(xiàng)描述符展開:
                                63-60 59-56 55-52 51-48 47-44 43-40 39-36 35-32 31-28 27-24 23-20 19-16 15-12 11-8 7-4  3-0
Kernel_CS:0x00cf9a000000ffff -->0000  0000  1100  1111  1001  1010  0000  0000  0000  0000  0000  0000  1111  1111 1111 1111
Kernel_DS:0x00cf92000000ffff -->0000  0000  1100  1111  1001  0010  0000  0000  0000  0000  0000  0000  1111  1111 1111 1111
User_CS: 0x00cffa000000ffff -->0000  0000  1100  1111  1111  1010  0000  0000  0000  0000  0000  0000  1111  1111 1111 1111
User_DS: 0x00cff2000000ffff -->0000  0000  1100  1111  1111  0010  0000  0000  0000  0000  0000  0000  1111  1111 1111 1111

以下對(duì)描述符各位進(jìn)行解析:
描述符格式如下:
63-56位存放的是基地址31-24位,基地址都為0
55位也叫G位,在LINUX中都為1,等于1時(shí)段長以4k字節(jié)為單位,等于0時(shí)以字節(jié)為單位
54位也叫D位,在LINUX中都為1,等于1表示對(duì)該段的訪問為32位指令,等于0為16位指令
53位等于0
52位,CPU忽略該位,可由軟件使用.
51-48位存放的是段地址上限19-16位,都是1
47位也叫P位,在LINUX中都是1,表示4個(gè)段都在內(nèi)存中.
46-45位是DPL位,表示特權(quán)級(jí)別.分別有00(0級(jí))和11(3級(jí))兩種組合.
44位也叫S位,等于1時(shí)表示一般的代碼段或數(shù)據(jù)段,等于0時(shí)表示用于系統(tǒng)管理的系統(tǒng)段,如各類描述表.
43-41位叫做type位,因?yàn)楦魑恢g有著緊密聯(lián)系:
 43位也叫E位,等于1時(shí)表示代碼段,這時(shí)第42位叫C位,C位等于0時(shí)會(huì)忽視特權(quán)級(jí)別,C位等于1時(shí)會(huì)依照特權(quán)級(jí)別.這時(shí)41位叫R位,等于1時(shí)為可讀,為0時(shí)不可讀.
  43位等于0時(shí)表示數(shù)據(jù)段,這時(shí)第42位叫ED位,ED位等于0時(shí)向上伸(數(shù)據(jù)段),ED位等于1時(shí)向下伸(堆棧段),這時(shí)41位叫W位,等于1時(shí)為可寫,為0時(shí)不可寫.
40位叫A位,在LINUX中都是1,表示以被訪問過.
39-16位存放的是基地址23到0位,基地址都為0.
15-0位存放的是段地址上限15-0位,都是1

結(jié)論:每個(gè)段都是從0地址開始的整個(gè)4GB虛存空間,虛地址到線線地址的映射保持原值不變.
因此,LINUX內(nèi)核的頁式映射,可以直接將線性地址當(dāng)作虛擬地址.二者完全一致.


3.3)頁式映射

3.3.1)頁式映射的概念:

1)在I386 CPU中頁式存儲(chǔ)的基本思路是:通過頁面目錄和頁面表分兩個(gè)層次實(shí)現(xiàn)從線性地址到物理地址的映射.
2)在LINUX中要考慮到各種不同的CPU,它以一種假想的,虛擬的CPU和MMU為基礎(chǔ),設(shè)計(jì)出一種通用的模型,再把它分別落實(shí)到各種具體的CPU上.
因此,LINUX內(nèi)核的映射機(jī)制設(shè)計(jì)成三層,在頁面目錄和頁面表中間增設(shè)了一層"中間目錄".
邏輯上的三層映射對(duì)于i386 CPU和MMU就變成了二層映射,把中間目錄PMD這一層跳過了,但是軟件的結(jié)構(gòu)卻還保持著三層映射的框架.
3)頁面目錄稱為PGD,中間目錄稱為PMD,頁面表則稱為PT.PT的表項(xiàng)則稱為PTE.
頁面目錄,中間目錄,頁目表三者均為數(shù)組.
4)邏輯上把線性地址分成4個(gè)段位,分別用在頁面目錄PGD的偏移,中間目錄PMD中的偏移,頁表PT中的偏移以及物理頁面內(nèi)的偏移,而如果是I386的CPU則沒有中間目錄.
也就是被分成3個(gè)段位,分別是頁面目錄PGD的偏移,頁表pt中的偏移以及物理頁內(nèi)的偏移量.
5)每個(gè)進(jìn)程都有自己的頁目錄表和頁表,進(jìn)程的切換就是將當(dāng)前進(jìn)程的頁目錄表起始地址保存到CR3寄存器.


3.3.2)線性地址到物理地址的映射:

1)將一個(gè)進(jìn)程的頁面目錄起始地址裝入寄存器CR3.
2)用線性地址的第1個(gè)段位即PGD的偏移,找到頁面表的物理地址.頁目錄表的大小為4k,剛好一個(gè)頁的大小,包含1024項(xiàng),每項(xiàng)4個(gè)字節(jié)(32位)
3)用線性地址的第2個(gè)段位即PT的偏移,找到表項(xiàng),頁面表的大小也是4k,同樣包含1024項(xiàng),每項(xiàng)4個(gè)字節(jié)(32位)
4)得到表項(xiàng)的高20位+低12位0組成,這個(gè)高20就是物理地址的高20位,再加上線性地址的第3段位即12位的偏移就得到了最終的物理地址.


3.3.3)用實(shí)例來說明映射的過程:

第一步:通過頁目錄表找到頁面表
還是以上面的程序?yàn)槔?
hello程序執(zhí)行后,調(diào)用函數(shù)grreeting,這里的虛擬地址也就是線性地址為0x08048354
call   08048354 <greeting>
分解后的結(jié)果是:
0000 1000 0000 0100 1000 0011 0101 0100
第1個(gè)段位(高10位):
0000 1000 00
對(duì)映十進(jìn)制的32,也就是在頁目錄表的偏移32找到其頁面表的物理地址,也就是頁面表的指針,它的低12位是0,因?yàn)轫撁姹硎?KB大小,所以肯定是邊界對(duì)齊了.

第二步:通過頁面表找到頁的起始物理地址高
接下來是線性地址的第二個(gè)段位(中間10位):
00 0100 10 00
對(duì)映十進(jìn)制的72,也就是在剛才找到的頁面表的偏移72找到目標(biāo)頁的起始物理地址,高20位有效的地址,低12位填充為0.

第三步:得到最終的物理地址
通過找到的頁起始物理地址,加上線性地址的第三個(gè)段位的偏移地址得到最終的物理地址.
例如:
第三個(gè)段位:0011 0101 0100
對(duì)映16進(jìn)制為0x354
如果目標(biāo)頁的起始物理地址為:0x740000,那么最終的物理地址就是:
0x740000+0x354=0x740354

本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/wishfly/archive/2010/05/21/5613931.aspx



本文來自CSDN博客,,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/hshl1214/archive/2010/08/09/5799690.aspx

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多