Linux X86 64位虛擬位址空間布局與試驗

2021-08-06 06:42:07 字數 2907 閱讀 2485

在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 segmentdata segmentbss segmenttext segment其實就是存放二進位制可執行**的位置,所以它的許可權是讀與可執行,data segment存放的是靜態常量,所以該位址段許可權是唯讀,bss segment存放未初始化的靜態變數,所以也就是可以隨意讀寫。

接下來是heap位址段,heap位址是往高位址增長的,是用來動態分配記憶體的區域。它跟棧相反,是往高位址增長的,對應的記憶體申請系統呼叫是brk()

再下面就是stack位址段了。這個棧已經用了136kb了。棧的最大範圍,我們可以通過prlimit命令看到,預設的情況下是8mb,和linux-x86一樣。

再下面就是vvarvdsovsyscall了。這三個東西都為了加速訪問核心資料,比如讀取時間gettimeofday,肯定不能頻繁地進行系統呼叫陷入核心,所以就對映到使用者空間了。所有程式都有這3個對映位址段。

關於vvar,vdso和vsyscall。先說vsyscall,這東西出現最早,比如讀取時間gettimeofday,核心會把時間資料和gettimeofday的實現對映到這塊區域,使用者空間可以直接呼叫。但是vsyscall區域太小了,而且對映區域固定,有安全問題。後來又造出了vdso,之所以保留是為了相容使用者空間程式。vdso相當於載入乙個linux-vd.so庫檔案一樣(名字也由此而來),也就是把一些函式實現對映到這個區域,而vvar也就是存放資料的地方了,那麼使用者可以通過呼叫vdso裡的函式,使用vvar裡的資料,來獲得自己想要的資訊。而且位址是隨機的,更安全。

具體的x64的記憶體布局如下圖所示:

可以發現裡面有不少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堆大小變回去了。再回車發現會產生段錯誤,因為記憶體已經被**,程序無法使用該記憶體位址。

#include 

#include

#include

#include

#include

int main()

printf("program allocate :%p\n", addr);

getchar();

if(munmap(addr, 1024) != 0)

return

0;}

在mmap之後,發現大小變成了20kb,剛好是我們申請了8kb

注意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...