學了好久終于搞懂fork函數的一些作用
1. fork函數作用:用于創建新的子進程
這是fork最根本的功能,在父進程里創建新的子進程、
但是創建新的子進程之后呢?
子進程和父進程的關系是什么樣的?
為什么fork得到的子進程返回值為0,父進程得到的返回值是子進程pid?
以及多級fork函數調用,得到曾曾……曾孫子進程返回的pid是多少呢?
2. 繼承父進程的一切
調用fork函數之后,父進程會創建一個幾乎一模一樣的子進程出來
幾乎一模一樣是什么意思?
- 子進程的代碼和父進程完全相同
- 子進程的變量以及變量的值和父進程完全相同,包括全局變量,局部變量都相同,但是唯一的不同就是fork()函數的返回值不同,如果用一個變量接受fork函數返回值,那么父子進程這個變量的值就會不同
- 比如:父進程執行fork函數創建子進程,這個fork函數在父進程里返回的是子進程的 PID; 在子進程里返回的是 0
- 這是為了區分父子,因為他們完全一模一樣的話操作系統也不知道誰是爹誰是兒了,就不方便管理,僅此而已
- 執行順序也相同,子進程會接著父進程的執行順序繼續往下執行,也就是接著執行父進程執行fork()創建自己之后的代碼,要注意的是如果子進程是在父進程的分支創建,那么子進程也就只能接著這個分支繼續執行,也就是說,子進程和父進程執行邏輯一樣,不會執行另一個分支,后面我們有題目講解
再次提醒,fork在父進程的返回值是子進程pid,在子進程中返回0
父子關系判斷很簡單:這個fork函數誰調用的誰就是爹,被創建的兒子接著fork往下執行
3. 子進程創建新的子進程,子子孫孫無窮匱也?
父進程執行fork創建子進程A,子進程A也執行fork創建孫子進程B
我們知道父進程中執行一個fork返回子進程A的pid,且這個fork在子進程A會返回0
那么子進程A執行另一個fork創建孫子進程B,這個fork在子進程A的返回值是什么呢?
答案如下:
子進程A執行fork()創建孫子進程B,該fork在子進程A中返回孫子進程B的pid
那么聰明的你一定知道該fork在孫子進程B中返回值是0
因為子進程A執行fork函數創建孫子進程B,A是B的父親,所以在中A返回B的PID,在B中返回0
4. 讀如下代碼,寫出執行結果,并描述父子關系
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
?
int main()
{pid_t pid1, pid2, pid3;pid1 = 0, pid2 = 0, pid3 = 0;pid1 = fork();if (pid1 == 0){pid2 = fork();pid3 = fork();}else{pid3 = fork();if (pid3 == 0){pid2 = fork();}if ((pid1 == 0) && (pid2 == 0)){printf("Level 1\n");}if (pid1 != 0){printf("Level 2\n");}if (pid2 != 0){printf("Level 3\n");}if (pid3 != 0){printf("Level 4\n");}}return 0;
}
分析
-
父進程創建子進程1,pid1記錄fork()返回值,也就是子進程1的pid,這里用pid1代指子進程1
-
父進程繼續執行,遇到if-else分支,父進程的pid1保存子進程1的pid,不為0,進入else分支
-
父進程再次創建子進程2,pid3保存子進程2的pid
-
父進程的pid1和pid3不為0,pid2 = 0,故進入if(pid1!=0)和if(pid3!=0)分支,輸出Level 2 和Level 4父進程結束
-
-
子進程1從pid1 = fork()之后開始執行,pid1 = fork返回值0,且子進程1繼承父進程的pid2、pid3,所以子進程進入if分支
-
子進程創建孫子進程1,pid2 = 孫子進程1的pid,孫子進程還會創建曾孫子進程1
-
創建孫子進程2,pid3 = 孫子進程2的pid
-
子進程1結束
-
孫子進程1和孫子進程2以及曾孫子進程1都在if分支里,不會到else分支去,故不輸出
-
-
子進程2從else 分支的第一個fork函數后開始運行,故pid3 = 0 (fork()返回值),繼承父進程的 pid1 = 子進程1的pid,pid2 = 0
-
進入if(pid3 ==0)分支,創建孫子進程3,pid2 = 孫子進程3的pid
-
子進程2進入if(pid1 != 0) 和if(pid2 != 0)分支,分別輸出Level 2和Level 3
-
子進程2結束
-
-
孫子進程3的pid2 = 0 (fork返回值),繼承子進程2的pid1 = 子進程1的pid,pid3 = 0
-
進入if(pid1 != 0)分支,輸出Level 2
-
故答案為:
Level 2
Level 4
Level 2
Level 3
Level 2
執行結果如下: