父進程 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
- 子進程拷貝父進程的數據,數據地址(虛擬地址)是一樣的。
- 父進程 alloc 了一次數據,delete 了兩次數據,子進程只是拷貝了父進程數據,沒有跑父進程 fork 前的代碼邏輯。
3.子進程有自己的獨立空間, 子進程修改數據後,copy-on-write,子進程空間將分配新的數據空間存儲新數據(top 查看進程負載情況)。
參考
- 《深入理解計算機系統》第二部分,8.4 章 進程控制
- 更精彩內容,可以關注我的博客:wenfh2020.com