Process

在 mmap() 的情況下,程序及其子程序如何使用記憶體?

  • January 22, 2022

假設我們正在使用 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))。

引用自:https://unix.stackexchange.com/questions/687403