Process
在 mmap() 的情況下,程序及其子程序如何使用記憶體?
假設我們正在使用 mmap() 創建一個共享記憶體。假設總記憶體大小為 4096。如果我們使用 fork() 系統呼叫來創建孩子,孩子會使用相同的記憶體,還是需要有自己的記憶體才能工作?
上
fork()
父程序的記憶體空間被複製到子程序中。作為一種優化,現代作業系統使用 COW(寫時複製),因此所有私有記憶體都與子程序共享,直到其中一個程序執行更改。然後受影響的記憶體頁面被複製。子程序和父程序在不同的記憶體空間中執行。在 fork() 時,兩個記憶體空間具有相同的內容。由其中一個程序執行的記憶體寫入、文件映射 (mmap(2)) 和取消映射 (munmap(2)) 不會影響另一個程序。
“兩個記憶體空間具有相同的內容”包括分配的記憶體
mmap()
。記憶體映射被複製,mmap()
或者munmap()
在 fork 之後不再影響其他程序。只有在 fork 之前使用
MAP_SHARED
(或特定於 Linux 的MAP_SHARED_VALIDATE
)映射的記憶體才會更改在程序之間傳播的內容。MAP_SHARED
共享此映射。映射的更新對於映射同一區域的其他程序是可見的,並且(在文件支持的映射的情況下)被傳遞到底層文件。(要精確控制何時對底層文件進行更新,需要使用 msync(2)。)
有一些 Linux 特定的映射標誌可以以其他方式修改行為:
- 使用 madvise(2) MADV_DONTFORK 標誌標記的記憶體映射不會通過 fork() 繼承。
- 在 fork() 之後,已用 madvise(2) MADV_WIPEONFORK 標誌標記的地址範圍內的記憶體在子代中歸零。(MADV_WIPEONFORK 設置對於孩子中的這些地址範圍保持不變。)
在
exec()
記憶體映像上被新程序替換,因此所有繼承的記憶體映射fork()
都被刪除。在 execve() 期間保留所有程序屬性,但以下情況除外:
$$ … $$
- 不保留記憶體映射 (mmap(2))。
- 附加的 System V 共享記憶體段被分離 (shmat(2))。
- POSIX 共享記憶體區域未映射 (shm_open(3))。