函數原型: pid_t fork(void)
頭文件: #include <unistd.h>
函數功能: 創建一個子進程
返回值: 1. -1 創建失敗
2. 0 返回的是子進程
3. >0 返回的是父進程,返回值是子進程ID
函數特性: 1. 調用一次,會有兩個返回值
2. 先返回哪個值,不確定,一般先返回父進程
3. 用戶可以通過延時函數,決定進程的執行先后順序。
4. 創建后,子進程復制父進程空間,這個空間子進程所獨有的只有它的進程號、計數器和資源使用,其他的和父進程
空間一樣,兩個空間相互獨立,互不干涉即使全局變量,在子進程中不會隨父進程中變量的值的改變而改變。
函數框架:
1 #inlcude <stdio.h> 2 #include <unisd.h> 3 int main() 4 { 5 pid_t pid; 6 //父進程獨有 7 pid = fork(); 8 //父子進程共有 9 if(pid < 0) 10 { 11 printf(“establish error!\n”); 12 return -1; 13 } 14 else if(pid == 0) 15 { 16 //子進程獨有 17 //子進程 18 } 19 else if(pid > 0) 20 { 21 //父進程獨有 22 //父進程 23 } 24 //父子進程共有 25 }
分析:獨有的只會運行一次,共有的會運行兩次。
進程切換: 1. 通過延時類函數(可控): sleep(s延時) usleep(us延時)
2. 時間片到了(不可控)
注意: 延時會讓程序處於等待態,所謂等待態,就是先去運行已經處於就緒態的程序,什么時候延時時間到了,程序
就會處於就緒態。等其他程序運行完,或者時間片到了,再切換回來,從上次的斷點處繼續運行。兩個進程之間
沒有優先級關系,不存在打斷關系,只有子進程運行完了,或者進入等待態,或者時間片到了才會進入父進程。
示例: 下面的代碼示例,如果沒有時間片的影響,在進入子進程以后,會一直卡在子進程,永遠不會再回到父進程,因
受時間片的影響,還會過一段時間就切換回父進程。
#include <stdio.h> 2 #include <unistd.h> 3 int main() 4 { 5 int num_father = 1; 6 int num_son = 1; 7 pid_t pid; 8 pid = fork(); 9 if(pid < 0) 10 { 11 printf("error\n"); 12 return -1; 13 } 14 else if(pid == 0) 15 { 16 num_son++; 17 printf("son\n"); 18 while(1) 19 { 20 printf("num_son=%d\n",num_son); 21 } 22 } 23 else if(pid >0) 24 { 25 num_father++; 26 printf("father\n"); 27 while(1) 28 { 29 usleep(1); 30 printf("num_father = %d\n",num_father); 31 } 32 } 33 }
代碼最終運行結果是:一直打印num_son,偶爾會打印num_father。原因是卡在子進程了,因為時間片到了才會切回父進程,但是很快又回到了子進程。
執行流程:1. 父進程運行后,遇到fork()之前,都是父進程獨有的程序
2. 當遇到fork函數后,開始創建子進程,一般先返回父進程
3. 在進入if框架之前,fork下的程序是子進程和父進程共有的
4. 進入pid>0父進程獨有的框架,如果父進程獨有中無等待類操作,父進程獨有的運行完,接着運行if框架外程序,
直到父進程運行完,然后再運行子進程,這時候子進程已經變為了孤兒進程。
1 #inlcude <stdio.h> 2 #include <unisd.h> 3 int main() 4 { 5 pid_t pid; 6 //父進程獨有 7 pid = fork(); 8 //父子進程共有 9 if(pid < 0) 10 { 11 printf(“establish error!\n”); 12 return -1; 13 } 14 else if(pid == 0) 15 { 16 //子進程獨有 17 //子進程 18 } 19 else if(pid > 0) 20 { 21 //父進程獨有 22 //父進程 23 } 24 //父子進程共有 25 }
運行步驟:
運行分析: fork有兩個返回值,但是返回順序有先后關系,第一個返回值是>0,先運行的是父進程,pid>0的elseif運行結束后,
父進程就結束了,此時,子進程變成了孤兒進程,被祖先進程接收,因為會返回兩個返回值,所以又會返回一個
值,程序從fork函數處又運行一遍,此時返回的是=0返回值的值,此時再運行==0的elsif。
示例代碼:
創建進程程序模板:
條件: 1.避免孤兒進程和僵屍進程
2.不存在父子進程共有的,全是獨有的