以問題形式講解
1.每一個進程都有一個堆空間嗎?還是多個進程共用一個堆空間?
在操作系統中,??每個進程都有自己獨立的虛擬地址空間,其中包括自己獨占的堆空間。堆空間是進程私有的,不與其他進程共享。
進程之間的內存在默認情況下不是共享的。
- 堆是每個進程私有的??。進程A在堆上分配的內存,進程B無法直接訪問。
- 如果進程A崩潰,不會影響進程B的堆內存(穩定性保障)。
但是可以有一種例外情況:共享內存。
若需要多個進程共享內存,必須通過??顯式創建的共享內存區域??實現,例如:
- ??System V共享內存(
shmget
)?? - ??POSIX共享內存(
shm_open
?+?mmap
)?? - ??內存映射文件(
mmap
?+ 文件)??
這類共享內存??獨立于進程的私有堆空間??,是專門申請的區域。
補充一點:
內核空間部分??(例如Linux中高地址的0xC0000000
以上區域)
??所有進程的虛擬內存映射指向同一物理內核區域??,內容完全相同。
但當進程進入內核態時(如系統調用、中斷):
- ??每個進程有自己獨立的內核棧??(kernel stack)
- 用于保存該進程在內核態執行的:
- 函數調用鏈
- 臨時變量
- 系統調用參數
例如Linux中每個進程的
task_struct
都包含一個void *stack
指針指向其獨有的內核棧(通常8KB大小)。
2.linux給每個進程分配8MB的棧空間大小。那如果有多個進程并發運行,但每個進程又沒有用到太多的棧空間,不會浪費內存嗎?
必須要明確的是這8MB的空間是虛擬內存不是物理內存。有虛擬內存和MMU存在就確保了即使有數百個進程并行運行,也不會造成顯著的物理內存浪費。
在 Linux 系統中,每個進程的??用戶棧空間默認被分配 8MB 的虛擬地址空間??,但這??并不等價于物理內存的實際占用??。設計上的關鍵點在于??按需分配的物理內存管理機制??,它確保了即使有數百個進程并行運行,也不會造成顯著的物理內存浪費。以下是詳細分析:
棧空間的本質:虛擬內存 vs 物理內存??
-
??虛擬地址空間??:
Linux 為每個進程預留 ??8MB 的虛擬地址范圍??(默認值,可通過?ulimit -s
?調整)。這部分地址空間是??邏輯上預留的區間??,并不是實際內存。 -
??物理內存分配??:
操作系統通過??按需分頁(Demand Paging)?? 機制管理物理內存:-
只有當進程真正??訪問棧地址??時(例如壓入函數參數或局部變量),內核才會分配物理內存頁(通常每頁 4KB)。
-
未使用的虛擬地址空間僅消耗??頁表條目??(約幾十字節),不占物理內存。
-
舉個例子:
假設系統運行 100 個并發進程,每個進程用戶棧虛擬大小為 8MB:
- ??虛擬地址空間總量??:100 × 8MB = ??800 MB??(看似很大,但這是虛擬內存)。
- ??物理內存實際占用??:
- 若每個進程平均只使用 200 KB 棧空間(常見場景),物理內存占用為 100 × 200 KB = ??20 MB??。
- 若進程棧使用更少(如 10 KB),則占用可低至 ??1 MB??。
只有 ??2.5% 的虛擬地址空間??(200 KB / 8MB)真正映射到物理內存。其余 97.5% 只是預留地址,不消耗物理資源。
3.一個進程中的函數A調用的函數B,執行函數B時會給函數B中的局部變量在棧中分配內存空間,那么當函數B執行完成后,這個棧空間會被回收嗎?
? ??邏輯回收是立即的??:函數返回時棧指針復位,空間可被后續函數重用
? ??物理回收是惰性的??:
- 正常情況 → 由??后續函數調用覆蓋重用??
- 無后續調用 → ??內核在內存壓力時回收??(可能延遲數十秒)
- 極限情況 → ??進程退出時100%回收?
4.linux嵌入式在啟動時要初始化棧。這里的棧指的是內核進程的棧還是init進程的棧又或者是shell進程的棧?
在嵌入式 Linux 系統啟動過程中,棧的初始化是多層次的,??貫穿從硬件初始化到用戶空間的全過程??。
必然然初始化??:
- Bootloader 棧:用于 U-Boot/CFE 等 bootloader 初始化硬件、加載內核
- 內核臨時棧:內核解壓、早期內存管理初始化
- 0 號進程(idle)內核棧:每個 CPU 核心一個,用于系統空閑時運行
- 1 號進程(init)內核棧:承載 init 進程在內核態的操作
- init 進程用戶棧:內核切換到用戶空間前,通過?
execve()
?系統調用加載 init 程序時創建
按需初始化??:
- Shell 進程用戶棧(僅在啟用交互式 shell 時創建