今天,師兄問我一個問題說:小濤啊,創(chuàng)建兩個進(jìn)程太簡單了,怎么創(chuàng)建多個進(jìn)程呢?我說那還不容易,看下邊代碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | int main()
{
pid_t pid[2];
int i;
printf ( "This is %d\n" ,getpid());
for (i = 0;i < 2;i++ ){
if ((pid[0] = fork()) < 0){
printf ( "Fork() Error!" );
exit (-1);
}
if (pid[0] == 0)
printf ( "This is parent %d,child is %d\n" ,getppid(),getpid());
else
wait(5);
}
return 0;
}
|
好,這段代碼還是挺簡單的,我們的意思是:主線程通過循環(huán)創(chuàng)建2個子進(jìn)程,這時系統(tǒng)中的總進(jìn)程數(shù)應(yīng)該是3,看看輸出結(jié)果吧:
這個結(jié)果圖看的效果不好,我們看個直接點的:
這下你明白了吧,問題沒有想象中的那樣簡單,父進(jìn)程現(xiàn)在標(biāo)號為1的循環(huán)中創(chuàng)了一個子進(jìn)程,然后第二次循環(huán),前邊的兩個線程個創(chuàng)建一個子進(jìn)程,這時明顯系統(tǒng)中有四個進(jìn)程,還是不懂?在下邊的時序圖吧:
這下你應(yīng)該明白了吧,好了問題知道了,怎么解決,方法有二;
方法一:直接看代碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | void createsubprocess( int num)
{
pid_t pid;
int i;
for (i=0;i<num;i++)
{
pid=fork();
if (pid==0||pid==-1)
{
break ;
}
}
if (pid==-1)
{
perror ( "fail to fork!\n" );
exit (1);
}
else if (pid==0)
{
printf ( "子進(jìn)程id=%d,其對應(yīng)的父進(jìn)程id=%d\n" ,getpid(),getppid());
exit (0);
}
else
{
printf ( "父進(jìn)程id=%d\n" ,getpid());
exit (0);
}
}
|
這種方法的關(guān)鍵就在于每次循環(huán)時,如果發(fā)現(xiàn)是子進(jìn)程就直接從創(chuàng)建子進(jìn)程的循環(huán)中跳出來,不讓你進(jìn)入循環(huán),這樣就保證了每次只有父進(jìn)程來做循環(huán)創(chuàng)建子進(jìn)程的工作。
方法二:直接看代碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | void createsubprocess( int num, int max)
{
if (num>=max) return ;
pid=fork();
if (pid<0)
{
perror ( "fork error!\n" );
exit (1);
}
else if (pid==0)
{
sleep(3);
printf ( "子進(jìn)程id=%d,父進(jìn)程id=%d\n" ,getpid(),getppid());
}
else
{
num++;
if (num==1) printf ( "父進(jìn)程id=%d\n" ,getpid());
if (num<max)createsubprocess(num,max);
sleep(5);
}
}
|
這里的關(guān)鍵在于遞歸操作,只有父進(jìn)程才進(jìn)入遞歸創(chuàng)建子進(jìn)程,子進(jìn)程不進(jìn)行這樣的操作。