深入理解程序的結構
阿新 • • 發佈:2018-03-30
程序結構 數據段 代碼段深入理解程序的結構
1靜態可執行程序中的段
程序由不同的段構成(代碼段、數據段),程序的靜態特征就是指令和數據,動態特征就是執行指令處理數據。
源程序代碼到可執行程序的對應關系:
代碼段
- 源代碼的可執行語句編譯後進入代碼段,編譯完成後大小固定
- 代碼段在內存管理單元的系統中具有只讀屬性(是一種保護,防止被改寫)
- 代碼段中可以包括常量數據(如字符串常量)
數據段(.data .bss .rodata)
.bss段(Block Started by Symbol segment)
存儲未初始化的全局數據,不占用可執行文件的大小。
.data段:存儲具有非0初始值的變量
.rodata段:存儲const修飾的和其他只讀數據
.bss段中的變量不用在再程序文件中保存初始值,從而減小可執程序的大小,提高程序加載的效率。(對於.bss段中的變量,在可執行文件中只需要保存其變量名和變量類型,在加載時統一將其初始化為0;而對於存儲於.data段中的數據,需要保存其變量名,類型、和值,在加載其需要將變量值拷貝得到變量對應的空間)
編程實驗:可以編寫簡單測試程序,通過objdump -h命令查看各個段的信息,使用nm命令查看可執行文件中的符號和地址,使用objdump -s -j .data ./a.ou查看某個段中的具體信息,並將上述信息對應起來。6.2動態加載後生成的段
棧(stack)
棧時在程序被加載到內存之後才生成的,其本質時片連續的存儲空間
SP寄存器作為棧頂“指針”實現入棧操作和出棧操作
棧通常作為以下用途
中斷發生時,棧用於保存寄存器的值(現場保護)
函數調用時,棧用於保存函數的活動記錄(棧幀信息)
並發編程時,每個線程擁有自己獨立的棧堆(Heap)
堆和棧一樣,時程序被加載到內存後才生成的。是一片“空閑的空間”,用於提供動態內存分配。
需要函數的支持(malloc、free)
內存映射段(memory mapping segment)
內核將硬盤中的文件內容直接映射到內存映射段(mmap)
動態鏈接庫在可執行程序加載時映射到內存映射段
內存映射文件的原理:
將硬盤上的文件數據邏輯映射到內存中(零耗時),通過缺頁中斷進行文件數據的實際載入(一次數據拷貝),映射後對內存的讀寫就是對文件的讀寫(極大的提高了文件的讀寫效率)。
使用傳統的方式通過read函數來讀取文件,首先內核程序接到應用程的請求,然後內核程序去讀取硬盤中的文件內核空間,然後再講內核空間中的數據拷貝到應用空間(使用了兩次數據拷貝)。
最終各個段在內存中的布局:
這裏我們看到棧、堆的起始地址都是隨機的,這樣做的目的是為了安全,當其實地址隨機後,惡意代碼修改程序的暗度變大(難以直接通過固定地址獲取到程度的返回地址)。
深入理解程序的結構