Fork同時建立多個子進程方法html
第一種方法:驗證經過 linux
特色:同時建立多個子進程,每一個子進程能夠執行不一樣的任務,程序 可讀性較好,便於分析,易擴展爲多個子進程 函數
#include <stdio.h> #include <pthread.h> int main(void) { printf("before fork(), pid = %d\n", getpid()); pid_t p1 = fork(); if ( p1 == 0 ) { printf("in child 1, pid = %d\n", getpid()); return 0; //若此處沒有return 0 p1 進程也會執行 pid_t p2=fork()語句 } pid_t p2 = fork(); if ( p2 == 0 ) { printf("in child 2, pid = %d\n", getpid()); return 0; //子進程結束,跳回父進程 Printf("hello world\n"); //沒有打印 } int st1, st2; waitpid( p1, &st1, 0); waitpid( p2, &st2, 0); printf("in parent, child 1 pid = %d\n", p1); printf("in parent, child 2 pid = %d\n", p2); printf("in parent, pid = %d\n", getpid()); printf("in parent, child 1 exited with %d\n", st1); printf("in parent, child 2 exited with %d\n", st2); return 0; }
[root@localhost ~]# gcc -o thread -pthread t.c
[root@localhost ~]# ./thread
before fork(), pid = 2629
in child 1, pid = 2630
in child 2, pid = 2631
in parent, child 1 pid = 2630
in parent, child 2 pid = 2631
in parent, pid = 2629
in parent, child 1 exited with 0
in parent, child 2 exited with 0url
第二種方法: 驗證經過 .net
特色:同時建立兩個子進程,結構比較繁瑣,程序可讀性很差,不易擴展 線程
#include<stdio.h> #include<unistd.h> #include<sys/types.h> //這個頭文件不能少,不然pid_t沒有定義 main() { printf("This is parent process%d\n",getpid()); pid_t p1,p2; if((p1=fork())==0) { printf("This is child_1 process%d\n",getpid()); }else { if((p2=fork())==0) { printf("This is child_2 process%d\n",getpid()); }else { wait(p1,NULL,0); wait(p2,NULL,0); printf("This is parent process%d\n",getpid()); } } }
第三種方法:for 循環方法 code
特色:其實每次循環只是建立了單個進程,並無同時建立多個進程 htm
#include<stdio.h> #include<unistd.h> #include<sys/types.h> main() { printf("This is parent process%d\n",getpid()); pid_t p1,p2; int i; for(i=0;i<=2;i++) { if((p1=fork())==0) { printf("This is child_1 process%d\n",getpid()); return 0;//這個地方很是關鍵 } wait(p1,NULL,0); //父進程等待p1子進程執行後才能繼續fork其餘子進程 printf("This is parent process%d\n",getpid()); } }
注意:標註的 return 0 對程序結果影響很大 blog
無 return 0 狀況 遞歸
#include<stdio.h> #include<unistd.h> #include<sys/types.h> main() { printf("This is parent process%d\n",getpid()); pid_t p1,p2; int i; for(i=0;i<=2;i++) { if((p1=fork())==0) { printf("This is child_1 process%d\n",getpid()); //return 0;//這個地方很是關鍵 } wait(p1,NULL,0); printf("This is parent process%d\n",getpid()); } }
結論:父進程會生成 n(n+1)/2+1個子進程,N 爲循環次數,本例中共有 7 個子進程, 但實際上只有 3 個是父進程產生的,其他都爲子進程 fork()出來的。父進程fork了3個進程,第一個子進程執行完以後又fork了2個進程,第2個子進程fork了1個進程。
正確的使用Linux中的用fork()由一個父進程建立同時多個子進程 的格式以下:
int status,i; for (i = 0; i < 10; i++) { status = fork(); if (status == 0 || status == -1) break;//每次循環時,若是發現是子進程就直接從建立子進程的循環中跳出來,不讓你進入循環,這樣就保證了每次只有父進程來作循環建立子進程的工做 } if (status == -1) { //error } else if (status == 0) //每一個子進程都會執行的代碼 { //sub process } else { //parent process }
原文地址:http://www.cnblogs.com/hanyan225/archive/2011/07/22/2113606.html
怎麼建立多個進程呢?我說那還不容易,看下邊代碼:
//省略必要頭文件 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; }
好,這段代碼仍是挺簡單的,咱們的意思是:主線程經過循環建立2個子進程,這時系統中的總進程數應該是3,看看輸出結果吧:
這下你明白了吧,問題沒有想象中的那樣簡單,父進程如今標號爲1的循環中創了一個子進程,而後第二次循環,前邊的第一個子線程又建立一個子進程,這時明顯系統中有四個進程,仍是不懂?在下邊的時序圖吧:
這下你應該明白了吧,好了問題知道了,怎麼解決,方法有二;
方法一:直接看代碼 for循環
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("子進程id=%d,其對應的父進程id=%d\n",getpid(),getppid()); exit(0); } else { printf("父進程id=%d\n",getpid()); exit(0); } }
這種方法的關鍵就在於每次循環時,若是發現是子進程就直接從建立子進程的循環中跳出來,不讓你進入循環,這樣就保證了每次只有父進程來作循環建立子進程的工做。
方法二:直接看代碼 遞歸函數
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("子進程id=%d,父進程id=%d\n",getpid(),getppid()); } //父進程 else { num++; if(num==1)printf("父進程id=%d\n",getpid()); if(num<max)createsubprocess(num,max); //此處加sleep是爲了防止父進程先退出,從而產生異常 sleep(5); } }
這裏的關鍵在於遞歸操做,只有父進程才進入遞歸建立子進程,子進程不進行這樣的操做。