父進程執行到fork語句時,開始創建子進程,創建完成後fork返回子進程的pid。
子進程拷貝父進程在此時刻的變量狀態和所有代碼,並令此fork函數的返回值爲0,之後從fork函數後繼續執行。這也意味着,如果代碼中有多個fork函數順序執行,前面的fork創建的子進程會繼續執行後面的fork,從而導致進程總數大量增加。n個fork語句順序執行後總進程數爲1(初始進程)+1+2+3+...+n=n*(n+1)/2+1。
但是通常情況下,我們只希望從初始進程創建子進程,不希望創建的子進程繼續創建進程。這種情況下可以利用fork在父子進程中的返回值差異來區分,只讓初始進程創建子進程:
#include <unistd.h>
#include <iostream>
using namespace std;
#define subprocess_num 5 //子進程數量
pid_t pid[subprocess_num];
int main()
{
pid_t p=1;
int i;
for(i=0;i<subprocess_num&&p>0;++i) //保證每次都是初始進程執行fork()
pid[i]=p=fork();
return 0;
}
上述代碼中,創建了5個子進程,其父進程全部是初始進程。那麼該如何區分這5個子進程,讓它們做不同的事呢?
其實剛剛也有提到,子進程拷貝父進程在此時刻的變量狀態和所有代碼,並令此fork函數的返回值爲0,之後從fork函數後繼續執行。
假設初始進程中執行第n個fork(),創建第n個子進程爲SPn,則SP1中p=0,i=0+1,SP2中p=0,i=1+1,...,SPn中p=0,i=n。因爲SPn是初始進程的第n個fork()創建的,所以會在初始進程執行第n個fork()這個時刻複製變量i,此時初始進程中的i剛好循環到n-1。之後,SPn從此處代碼繼續執行for語句,i自加後跳出循環,故SPn中的i值爲n。
利用這一點就可以區分不同子進程,讓它們處理不同的分支:
#include <unistd.h>
#include <iostream>
using namespace std;
#define subprocess_num 5 //子進程數量
pid_t pid[subprocess_num];
int main()
{
pid_t p=1;
int i;
for(i=0;i<subprocess_num&&p>0;++i) //保證每次都是初始進程執行fork()
pid[i]=p=fork();
if(p>0)
{
cout<<"this is the first process"<<endl; //初始進程邏輯
}
if(p==0)
{
switch(i) //區分不同子進程
{
case 1:cout<<"this is SP1"<<endl;break;
case 2:cout<<"this is SP2"<<endl;break;
case 3:cout<<"this is SP3"<<endl;break;
case 4:cout<<"this is SP4"<<endl;break;
case 5:cout<<"this is SP5"<<endl;break;
default:cout<<"error"<<endl;break;
}
}
return 0;
}