系統調用fork()用於創建一個新進程。我們可以通過下面的代碼來理解,最好是能自己敲一遍運行驗證。
#include<stdio.h> #include<stdlib.h> #include<unistd.h> int main(int args, char *argv[]){ printf("hello world (pid:%d)\n", (int) getpid()); int rc = fork(); if (rc < 0){ fprintf(stderr,"fork failed\n"); exit(1); }else if (rc == 0){ printf("hello, I am child (pid:%d)\n", (int) getpid()); }else{ printf("hello, I am parent of %d (pid:%d)\n",rc,(int) getpid()); } return 0; }
執行結果:
hello world (pid:18905) hello, I am parent of 18906 (pid:18905) hello, I am child (pid:18906)
整段代碼我們可以理解成三大步:
第一步:打印"hello world";
第二步:fork()一個新的進程;
第三步:判斷rc的返回值並打印對應的信息;
1)當rc<0時,表示fork一個新進程失敗;
2)當rc=0時,表示fork進入的是子進程;
3)當rc等於其他值時,表示fork進程成功,並將子進程的值賦值給rc。
從下面這張圖可以很清晰的看到,父進程執行的步驟是123,子進程執行的步驟是23。其中父進程和子進程執行第三步的時候是沒有先后順序的,由CPU調度程序(scheduler)決定在某個哪個進程被執行。也就是上面的結果,后面兩行每次打印的順序結果可能是不一樣的。
這里需要特別注意的是:
1、子進程不會從main()函數開始執行,而是直接從fork()系統調用返回,就好像是他自己調用了fork。
2、子進程並不是完全拷貝了父進程。雖然它擁有自己的地址空間(擁有自己的私有內存)、寄存器、程序計數器等,但是它從fork()返回的值是不一樣的。父進程獲得的返回值是新創建子進程的PID,而子進程獲得的返回值是0。