fork 進程測試 copy-on-write

父進程 fork 子進程後,子進程通過 copy-on-write 模式獲得父進程內存,也就是子進程共用了大部分父進程內存,只有當子進程在修改自己進程內存後,共享部分,纔會把那些修改的拷貝出來,這樣可以節省系統大量內存分配。


系統

macos


測試

測試對象申請一塊內存,主進程 fork 子進程後監測子進程對內存數據修改前後狀況。

子進程數據修改前

子進程數據修改後

測試進程跑得比較快,兩次抓圖的進程不一樣。感興趣的朋友可以拿源碼測試下。


測試源碼

源碼

alloc_data g_data;

int main() {
    pid_t pid = fork();
    if (0 == pid) {
        printf("child pid: %d, data ptr: %#lx\n", getpid(),
               (unsigned long)&g_data);
        sleep(5);  // update data before
        printf("child pid: %d, reset data:\n", getpid());
        g_data.reset();
        sleep(5);  // update data later
        exit(0);
    } else if (pid > 0) {
        printf("parent pid: %d, data ptr: %#lx\n", getpid(),
               (unsigned long)&g_data);
    } else {
        printf("fork fail\n");
        exit(1);
    }

    printf("parent end, pid: %d\n", getpid());
    return 0;
}

測試結果

alloc, data ptr: 0x602140, array ptr: 0x602148
parent pid: 29118, data ptr: 0x602140
child pid: 29126, data ptr: 0x602140
child pid: 29126, reset data:
reset data, data ptr: 0x602140, array ptr: 0x602148
delete data, pid: 29126
child 29126 terminated normally with exit status = 0
sig_child_handler end, errno: 0
parent end, pid: 29118
delete data, pid: 29118
  1. 子進程拷貝父進程的數據,數據地址(虛擬地址)是一樣的。
  2. 父進程 alloc 了一次數據,delete 了兩次數據,子進程只是拷貝了父進程數據,沒有跑父進程 fork 前的代碼邏輯。
    3.子進程有自己的獨立空間, 子進程修改數據後,copy-on-write,子進程空間將分配新的數據空間存儲新數據(top 查看進程負載情況)。

參考

  • 《深入理解計算機系統》第二部分,8.4 章 進程控制

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章