1. 程式人生 > >筆記—《程序員自我修養》

筆記—《程序員自我修養》

物理地址 區分 32位 extern 創建 內核線程 mon BE 直接

《程序員自我修養》 筆記

溫故而知新

平坦內存模型存在的問題

  • 進程之間地址空間不隔離
  • 多進程時, 內存碎片多(分頁), 內存利用效率低(緩存命中率)
  • 程序運行的地址空間不確定

分段

提高緩存命中率
讀寫權限隔離
提高內存利用效率(多個運行的線程可以共享一份代碼段)

分頁

提高內存利用率,減少內存碎片
和虛擬內存管理機制一起解決了內存不連續的問題(分配的內存一般是虛擬內存,在第一次使用虛擬內存發生缺頁中斷中才會真正分配物理內存)

線程 與 進程

Linux 下線程與進程都是使用同一個結構體task_struct來表示的,線程之間共享的內存結構來區分線程和進程之間的並發程度,內核線程 復制阻塞情況下的線程切換, 非阻塞的線程切換在用戶態處理。

線程的私有空間

Stack
寄存器
線程局部存儲

預處理,編譯,匯編,鏈接

靜態鏈接

目標文件(ELF格式)

.o 可重定位文件 有一個重定位表 rel.text 用於重定位符號
可執行文件
.so 共享目標文件,用於動態鏈接

文件內容

BSS 未初始化的靜態變量
COMMON 未初始化的全局變量(因為暫時不知道需要多少內存)
DATA 初始化的全局變量的靜態變量
TEXT
RODATA
符號表(重定位和符號決議)
文件頭 版本 大小 偏移量 magic number
重定位表 前置聲明的重定位

強符號 與 弱符號

前置聲明是弱符號, 定義/初始化是強符號,在副號決議的時候會優先對應強符號,多個強符號會報錯沖突。

符號修飾

C++的重載 對符號名的影響
命名空間 對符號名的影響

extern

函數聲明規範
函數,變量的 外連接性質

地址和空間分配 + 重定位和符號決議 = 鏈接

  1. 掃描輸入目標文件獲得各個段的長度,分配內存並維護一個全局符號表
  2. 根據全局符號表和重定位表 完成副號決議 和 重定位

main 函數之前和之後的內容

初始化進程環境,堆分配初始化,傳遞main 的參數,全局變量的初始化等。
.init 段:
.fini 段:

可執行文件的裝載與進程

32位平臺下的4G內存空間,1GB內核,1GB用戶態。

加載方式-頁映射

頁映射是虛擬存儲機制的一部分,隨著虛擬存儲的發明而誕生,數據和指令按頁劃分完畢後裝載,如果程序使用物理地址直接進行操作,那麽每次裝入頁都要進行重定位。

進程的建立

創建一個獨立的虛擬地址空間(分配一個頁目錄)
建立空間和可執行文件的映射關系(進程中VMA映射到ELF的.text段)
CPU寄存器設置為可執行文件入口地址

進程裝載細節

把相同權限的段合並在一起映射

堆棧分配

筆記—《程序員自我修養》