- 進程之間地址空間不隔離
- 多進程時, 內存碎片多(分頁), 內存利用效率低(緩存命中率)
- 程序運行的地址空間不肯定
提升緩存命中率 讀寫權限隔離 提升內存利用效率(多個運行的線程能夠共享一份代碼段)程序員
提升內存利用率,減小內存碎片 和虛擬內存管理機制一塊兒解決了內存不連續的問題(分配的內存通常是虛擬內存,在第一次使用虛擬內存發生缺頁中斷中才會真正分配物理內存)算法
Linux 下線程與進程都是使用同一個結構體task_struct來表示的,線程之間共享的內存結構來區分線程和進程之間的併發程度,內核線程 複製阻塞狀況下的線程切換, 非阻塞的線程切換在用戶態處理。緩存
Stack 寄存器 線程局部存儲bash
.o 可重定位文件 有一個重定位表 rel.text 用於重定位符號 可執行文件 .so 共享目標文件,用於動態連接併發
BSS 未初始化的靜態變量 COMMON 未初始化的全局變量(由於暫時不知道須要多少內存) DATA 初始化的全局變量的靜態變量 TEXT RODATA 符號表(重定位和符號決議) 文件頭 版本 大小 偏移量 magic number 重定位表 前置聲明的重定位函數
前置聲明是弱符號, 定義/初始化是強符號,在副號決議的時候會優先對應強符號,多個強符號會報錯衝突。spa
C++的重載 對符號名的影響 命名空間 對符號名的影響操作系統
函數聲明規範 函數,變量的 外鏈接性質線程
- 掃描輸入目標文件得到各個段的長度,分配內存並維護一個全局符號表
- 根據全局符號表和重定位表 完成副號決議 和 重定位
初始化進程環境,堆分配初始化,傳遞main 的參數,全局變量的初始化等。 .init 段: .fini 段:指針
32位平臺下的4G內存空間,1GB內核,1GB用戶態。
頁映射是虛擬存儲機制的一部分,隨着虛擬存儲的發明而誕生,數據和指令按頁劃分完畢後裝載,若是程序使用物理地址直接進行操做,那麼每次裝入頁都要進行重定位。將進程須要使用的數據和代碼部分以頁的形式分配虛擬內存,用內存置換算法來調度。
建立一個獨立的虛擬地址空間(分配一個頁目錄,在發生缺頁中斷時進行內存調度) 創建空間和可執行文件的映射關係(進程中VMA映射到ELF的.text段) CPU寄存器設置爲可執行文件入口地址(ELF文件頭中保存)
查詢頁目錄,找到缺頁中斷對應的VMA,計算在可執行文件中的 偏移量,而後在物理內存中分配頁面而且創建映射。
把相同權限的段合併在一塊兒映射
傳入參數 Argc Argv bash 進程 fork() + execve() 檢測ELF文件有效性,設置動態連接路徑,映射ELF文件,初始化ELF進程環境。
從操做系統角度來看,進程分配內存有兩種方式,分別由兩個系統調用完成:brk()和mmap()(不考慮共享內存)。
一、brk是將數據段(.data)的最高地址指針_edata往高地址推;
二、mmap是在進程的虛擬地址空間中(堆和棧中間,稱爲文件映射區域的地方)找一塊空閒的虛擬內存。
這兩種方式分配的都是虛擬內存,沒有分配物理內存(不許確,系統調用會執行內核函數,分配內存),在第一次訪問已分配的虛擬地址空間的時候,發生缺頁中斷,操做系統負責分配物理內存,而後創建虛擬內存和物理內存之間的映射關係。
- brk 的內存碎片
- mmap 的系統調用開銷