Linux中的地址空間分配原則

發(fā)布時(shí)間:2011-2-26 20:45    發(fā)布者:hikesoso2010
關(guān)鍵詞: linux , 空間分配
有這么一系列的問(wèn)題,是否在困擾著(zhù)你:用戶(hù)程序編譯連接形成的地址空間在什么范圍內??jì)群司幾g后地址空間在什么范圍內?要對外設進(jìn)行訪(fǎng)問(wèn),I/O的地址空間又是什么樣的?  

先回答第一個(gè)問(wèn)題。Linux最常見(jiàn)的可執行文件格式為elf(Executable and Linkable Format)。在elf格式的可執行代碼中,ld總是從0x8000000開(kāi)始安排程序的“代碼段”,對每個(gè)程序都是這樣。至于程序執行時(shí)在物理內存中的實(shí)際地址,則由內核為其建立內存映射時(shí)臨時(shí)分配,具體地址取決于當時(shí)所分配的物理內存頁(yè)面! 

我們可以用Linux的實(shí)用程序objdump對你的程序進(jìn)行反匯編,從而知曉其地址范圍! 

例如:假定我們有一個(gè)簡(jiǎn)單的C程序Hello.c  

# include   
greeting ( )  
{  
printf(“Hello,world!\n”);  
}  
main()  
{  
greeting();  
}  
之所以把這樣簡(jiǎn)單的程序寫(xiě)成兩個(gè)函數,是為了說(shuō)明指令的轉移過(guò)程。我們用gcc和ld對其進(jìn)行編譯和連接,得到可執行代碼hello。然后,用Linux的實(shí)用程序objdump對其進(jìn)行反匯編:  
$objdump -d hello  
得到的主要片段為:  
08048568 :  
8048568:     
pushl  %ebp  
8048569:     
movl  %esp, %ebp  
804856b:     
pushl  $0x809404  8048570:     
call    8048474  <_init+0x84>  8048575:     
addl   $0x4, %esp  8048578:   
leave  8048579:     
ret  804857a:     
movl  %esi, %esi  0804857c
:  
804857c:     
pushl  %ebp  804857d:     
movl  %esp, %ebp  804857f:   
call    8048568    8048584:     
leave  8048585:     
ret  8048586:     
nop  8048587:     
nop  
其中,像08048568這樣的地址,就是我們常說(shuō)的虛地址(這個(gè)地址實(shí)實(shí)在在的存在,只不過(guò)因為物理地址的存在,顯得它是“虛”的罷了)! 

虛擬內存、內核空間和用戶(hù)空間  

Linux虛擬內存的大小為2^32(在32位的x86機器上),內核將這4G字節的空間分為兩部分。最高的1G字節(從虛地址0xC0000000到0xFFFFFFFF)供內核使用,稱(chēng)為“內核空間”。而較低的3G字節(從虛地址0x00000000到0xBFFFFFFF),供各個(gè)進(jìn)程使用,稱(chēng)為“用戶(hù)空間”。因為每個(gè)進(jìn)程可以通過(guò)系統調用進(jìn)入內核,因此,Linux內核空間由系統內的所有進(jìn)程共享。于是,從具體進(jìn)程的角度來(lái)看,每個(gè)進(jìn)程可以擁有4G字節的虛擬地址空間(也叫虛擬內存)! ∶總(gè)進(jìn)程有各自的私有用戶(hù)空間(0~3G),這個(gè)空間對系統中的其他進(jìn)程是不可見(jiàn)的。最高的1GB內核空間則為所有進(jìn)程以及內核所共享。另外,進(jìn)程的“用戶(hù)空間”也叫“地址空間”,在后面的敘述中,我們對這兩個(gè)術(shù)語(yǔ)不再區分! 

用戶(hù)空間不是進(jìn)程共享的,而是進(jìn)程隔離的。每個(gè)進(jìn)程最大都可以有3GB的用戶(hù)空間。一個(gè)進(jìn)程對其中一個(gè)地址的訪(fǎng)問(wèn),與其它進(jìn)程對于同一地址的訪(fǎng)問(wèn)絕不沖突。比如,一個(gè)進(jìn)程從其用戶(hù)空間的地址0x1234ABCD處可以讀出整數8,而另外一個(gè)進(jìn)程從其用戶(hù)空間的地址0x1234ABCD處可以讀出整數20,這取決于進(jìn)程自身的邏輯! 

任意一個(gè)時(shí)刻,在一個(gè)CPU上只有一個(gè)進(jìn)程在運行。所以對于此CPU來(lái)講,在這一時(shí)刻,整個(gè)系統只存在一個(gè)4GB的虛擬地址空間,這個(gè)虛擬地址空間是面向此進(jìn)程的。當進(jìn)程發(fā)生切換的時(shí)候,虛擬地址空間也隨著(zhù)切換。由此可以看出,每個(gè)進(jìn)程都有自己的虛擬地址空間,只有此進(jìn)程運行的時(shí)候,其虛擬地址空間才被運行它的CPU所知。在其它時(shí)刻,其虛擬地址空間對于CPU來(lái)說(shuō),是不可知的。所以盡管每個(gè)進(jìn)程都可以有4 GB的虛擬地址空間,但在CPU眼中,只有一個(gè)虛擬地址空間存在。虛擬地址空間的變化,隨著(zhù)進(jìn)程切換而變化! 

從上面我們知道,一個(gè)程序編譯連接后形成的地址空間是一個(gè)虛擬地址空間,但是程序最終還是要運行在物理內存中。因此,應用程序所給出的任何虛地址最終必須被轉化為物理地址,所以,虛擬地址空間必須被映射到物理內存空間中,這個(gè)映射關(guān)系需要通過(guò)硬件體系結構所規定的數據結構來(lái)建立。這就是我們所說(shuō)的段描述符表和頁(yè)表,Linux主要通過(guò)頁(yè)表來(lái)進(jìn)行映射! 

于是,我們得出一個(gè)結論,如果給出的頁(yè)表不同,那么CPU將某一虛擬地址空間中的地址轉化成的物理地址就會(huì )不同。所以我們?yōu)槊恳粋(gè)進(jìn)程都建立其頁(yè)表,將每個(gè)進(jìn)程的虛擬地址空間根據自己的需要映射到物理地址空間上。既然某一時(shí)刻在某一CPU上只能有一個(gè)進(jìn)程在運行,那么當進(jìn)程發(fā)生切換的時(shí)候,將頁(yè)表也更換為相應進(jìn)程的頁(yè)表,這就可以實(shí)現每個(gè)進(jìn)程都有自己的虛擬地址空間而互不影響。所以,在任意時(shí)刻,對于一個(gè)CPU來(lái)說(shuō),只需要有當前進(jìn)程的頁(yè)表,就可以實(shí)現其虛擬地址到物理地址的轉化! 

.內核空間到物理內存的映射  

內核空間對所有的進(jìn)程都是共享的,其中存放的是內核代碼和數據,而進(jìn)程的用戶(hù)空間中存放的是用戶(hù)程序的代碼和數據,不管是內核程序還是用戶(hù)程序,它們被編譯和連接以后,所形成的指令和符號地址都是虛地址(參見(jiàn)2.5節中的例子),而不是物理內存中的物理地址! 

雖然內核空間占據了每個(gè)虛擬空間中的最高1GB字節,但映射到物理內存卻總是從最低地址(0x00000000)開(kāi)始的,如圖4.2所示,之所以這么規定,是為了在內核空間與物理內存之間建立簡(jiǎn)單的線(xiàn)性映射關(guān)系。其中,3GB(0xC0000000)就是物理地址與虛擬地址之間的位移量,在Linux代碼中就叫做PAGE_OFFSET! 

我們來(lái)看一下在include/asm/i386/page.h頭文件中對內核空間中地址映射的說(shuō)明及定義:  
#define __PAGE_OFFSET           
(0xC0000000)  ……  
#define PAGE_OFFSET            
((unsigned long)__PAGE_OFFSET)  
#define __pa(x)                 
((unsigned long)(x)-PAGE_OFFSET)  
#define __va(x)                 
((void *)((unsigned long)(x)+PAGE_OFFSET))  

對于內核空間而言,給定一個(gè)虛地址x,其物理地址為“x- PAGE_OFFSET”,給定一個(gè)物理地址x,其虛地址為“x+ PAGE_OFFSET”! 

這里再次說(shuō)明,宏__pa()僅僅把一個(gè)內核空間的虛地址映射到物理地址,而決不適用于用戶(hù)空間,用戶(hù)空間的地址映射要復雜得多,它通過(guò)分頁(yè)機制完成。
本文地址:http://selenalain.com/thread-56060-1-1.html     【打印本頁(yè)】

本站部分文章為轉載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀(guān)點(diǎn)和對其真實(shí)性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問(wèn)題,我們將根據著(zhù)作權人的要求,第一時(shí)間更正或刪除。
hszx 發(fā)表于 2011-2-27 12:03:14
yangjiansen 發(fā)表于 2011-3-10 14:36:00
好東西啊
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

相關(guān)視頻

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表
午夜高清国产拍精品福利|亚洲色精品88色婷婷七月丁香|91久久精品无码一区|99久久国语露脸精品|动漫卡通亚洲综合专区48页