在x86_64下面,其實虛擬位址只使用了48位。所以c程式裡,列印的位址都是只有12位16進製制。48位位址長度也就是對應了256tb的位址空間。
而在linux下有效的位址區間是從0x00000000 00000000 ~ 0x00007fff ffffffff
還有0xffff8000 00000000 ~ 0xffffffff ffffffff
兩個位址區間。而每個位址區間都有128tb的位址空間可以使用,所以總共是256tb的可用空間。位址空間的劃分就如下所示
下面分析使用者空間的位址布局。乙個程式的記憶體布局,可以通過ffffffff`ffffffff _____________
| |
| 核心空間 |
ffff8000`00000000
|____________|
| |
| 未使用 |
| 的空間 |
| |
00007fff`ffffffff |____________|
| |
| 使用者空間 |
00000000`00000000
|____________|
這是乙個簡單的helloworld程式的示例布局
前三行分別是text segment
、data segment
和bss segment
,text segment
其實就是存放二進位制可執行**的位置,所以它的許可權是讀與可執行,data segment
存放的是靜態常量,所以該位址段許可權是唯讀,bss segment
存放未初始化的靜態變數,所以也就是可以隨意讀寫。
接下來是heap
位址段,heap位址是往高位址增長的,是用來動態分配記憶體的區域。它跟棧相反,是往高位址增長的,對應的記憶體申請系統呼叫是brk()。
再下面就是stack
位址段了。這個棧已經用了136kb了。棧的最大範圍,我們可以通過prlimit
命令看到,預設的情況下是8mb,和linux-x86一樣。
再下面就是vvar
,vdso
和vsyscall
了。這三個東西都為了加速訪問核心資料,比如讀取時間gettimeofday
,肯定不能頻繁地進行系統呼叫陷入核心,所以就對映到使用者空間了。所有程式都有這3個對映位址段。
關於vvar,vdso和vsyscall。先說vsyscall,這東西出現最早,比如讀取時間具體的x64的記憶體布局如下圖所示:gettimeofday
,核心會把時間資料和gettimeofday
的實現對映到這塊區域,使用者空間可以直接呼叫。但是vsyscall區域太小了,而且對映區域固定,有安全問題。後來又造出了vdso,之所以保留是為了相容使用者空間程式。vdso相當於載入乙個linux-vd.so庫檔案一樣(名字也由此而來),也就是把一些函式實現對映到這個區域,而vvar也就是存放資料的地方了,那麼使用者可以通過呼叫vdso裡的函式,使用vvar裡的資料,來獲得自己想要的資訊。而且位址是隨機的,更安全。
可以發現裡面有不少random xx offset,這是linux裡的aslr策略。aslr的話就是address space layout randomization,是一種安全機制,主要防止緩衝區溢位攻擊。
brk系統呼叫可以通過調整heap區域的brk指標,從而調整heap對的虛擬記憶體空間大小。實驗**如下:
初始狀態#include
#include
#include
int main()
按回車,呼叫brk(curr_brk+4096)之後
看到heap大小從132kb變成了136kb,而且位址空間可以正常使用。再次回車,呼叫brk(tmp_brk)
發現heap堆大小變回去了。再回車發現會產生段錯誤,因為記憶體已經被**,程序無法使用該記憶體位址。
在mmap之後,發現大小變成了20kb,剛好是我們申請了8kb#include
#include
#include
#include
#include
int main()
printf("program allocate :%p\n", addr);
getchar();
if(munmap(addr, 1024) != 0)
return
0;}
注意mmap申請記憶體的時候,如果申請位址長度小於乙個page_size=2kb=4096位元組=0x1000位元組,那麼會直接申請2kb。而page_size的話可以通過getconf page_size
命令來檢視。
sysctl vm.mmap_min_addr
在debian下,它的預設值是4096。也就是你申請的首位址必須比0x1000大。 32位Linux系統虛擬位址對映
ia32體系即intel32位體系架構,也被稱為i386 x86 32或x86。在intel公司1985年推出的80386微處理器中首先使用。用以取代之前的x86 16位架構,包括8086 80186 80286晶元。談到這兒,就不得不說說x86架構的發展歷史。intel 8086是由intel於1...
Tomcat虛擬位址
當不想把jsp程式 網頁等編寫的程式檔案部署在tomcat的根目錄下時,虛擬目錄是最好的選擇。虛擬目錄實際上是在伺服器上做乙個對映,把某個名稱命名的目錄指向另外乙個事實上存在的目錄,這樣可以增強安全性,訪問者並不清楚伺服器是否確實有無目錄,當伺服器某個盤中的空間不夠時,可以把程式部署到另乙個盤中做虛...
虛擬位址空間
當處理器讀或寫入記憶體位置時,它會使用虛擬位址。作為讀或寫操作的一部分,處理器將虛擬位址轉換為實體地址。通過虛擬位址訪問記憶體有以下優勢 程序可用的虛擬位址範圍稱為該程序的 虛擬位址空間 每個使用者模式程序都有其各自的專用虛擬位址空間。對於 32 位程序,虛擬位址空間通常為 2 gb,範圍從 0x0...