應(yīng)該看兩遍!
          1. #include <sys/types.h>   
          2. #include <unistd.h>   
          3. /* 
          4. 功能:復(fù)制進(jìn)程 
          5. 參數(shù):無(wú) 
          6. 返回值:  成功:  父進(jìn)程:返回子進(jìn)程id 
          7.                 子進(jìn)程:返回0 
          8.          失敗:  返回-1 
          9. */  
          10. pid_t fork(void);  

           

          由fork創(chuàng)建的新進(jìn)程被稱為子進(jìn)程(child process)。該函數(shù)被調(diào)用一次,但返回兩次。兩次返回的區(qū)別是子進(jìn)程的返回值是0,而父進(jìn)程的返回值則是新進(jìn)程(子進(jìn)程)的進(jìn)程 id。將子進(jìn)程id返回給父進(jìn)程的理由是:因?yàn)橐粋€(gè)進(jìn)程的子進(jìn)程可以多于一個(gè),沒(méi)有一個(gè)函數(shù)使一個(gè)進(jìn)程可以獲得其所有子進(jìn)程的進(jìn)程id。對(duì)子進(jìn)程來(lái)說(shuō),之所以fork返回0給它,是因?yàn)樗S時(shí)可以調(diào)用getpid()來(lái)獲取自己的pid;也可以調(diào)用getppid()來(lái)獲取父進(jìn)程的id。(進(jìn)程id 0總是由交換進(jìn)程使用,所以一個(gè)子進(jìn)程的進(jìn)程id不可能為0 )。

          fork之后,操作系統(tǒng)會(huì)復(fù)制一個(gè)與父進(jìn)程完全相同的子進(jìn)程,雖說(shuō)是父子關(guān)系,但是在操作系統(tǒng)看來(lái),他們更像兄弟關(guān)系,這2個(gè)進(jìn)程共享代碼空間,但是數(shù)據(jù)空間是互相獨(dú)立的,子進(jìn)程數(shù)據(jù)空間中的內(nèi)容是父進(jìn)程的完整拷貝,指令指針也完全相同,子進(jìn)程擁有父進(jìn)程當(dāng)前運(yùn)行到的位置(兩進(jìn)程的程序計(jì)數(shù)器pc值相同,也就是說(shuō),子進(jìn)程是從fork返回處開始執(zhí)行的),但有一點(diǎn)不同,如果fork成功,子進(jìn)程中fork的返回值是0,父進(jìn)程中fork的返回值是子進(jìn)程的進(jìn)程號(hào),如果fork不成功,父進(jìn)程會(huì)返回錯(cuò)誤。
          可以這樣想象,2個(gè)進(jìn)程一直同時(shí)運(yùn)行,而且步調(diào)一致,在fork之后,他們分別作不同的工作,也就是分岔了。這也是fork為什么叫fork的原因

          至于那一個(gè)最先運(yùn)行,可能與操作系統(tǒng)(調(diào)度算法)有關(guān),而且這個(gè)問(wèn)題在實(shí)際應(yīng)用中并不重要,如果需要父子進(jìn)程協(xié)同,可以通過(guò)原語(yǔ)的辦法解決。

           

          一個(gè)fork例子

           

          1. #include <unistd.h>   
          2. #include <sys/types.h>   
          3. #include <stdio.h>   
          4. int main(void)  
          5. {  
          6.     pid_t pid;  
          7.     pid=fork();  
          8.     switch (pid)  
          9.     {  
          10.     case -1:  
          11.         perror("fork error");  
          12.         exit(1);  
          13.     case 0:  
          14.         printf("I am the child process, my process id is %d/n", getpid());  
          15.         break;  
          16.     default:  
          17.         printf("I am the parent process, my process id is %d/n", getpid());  
          18.         break;  
          19.     }  
          20.      return 0;  
          21. }   

           

          要搞清楚fork的執(zhí)行過(guò)程,就必須先弄清楚操作系統(tǒng)中的“進(jìn)程(process)”概念。一個(gè)進(jìn)程,主要包含三個(gè)元素:
          o. 一個(gè)可以執(zhí)行的程序;
          o. 和該進(jìn)程相關(guān)聯(lián)的全部數(shù)據(jù)(包括變量,內(nèi)存空間,緩沖區(qū)等等);
          o. 程序的執(zhí)行上下文(execution context)。

          不妨簡(jiǎn)單理解為,一個(gè)進(jìn)程表示的,就是一個(gè)可執(zhí)行程序的一次執(zhí)行過(guò)程中的一個(gè)狀態(tài)。操作系統(tǒng)對(duì)進(jìn)程的管理,典型的情況,是通過(guò)進(jìn)程表完成的。進(jìn)程表中的每一個(gè)表項(xiàng),記錄的是當(dāng)前操作系統(tǒng)中一個(gè)進(jìn)程的情況。對(duì)于單 CPU的情況而言,每一特定時(shí)刻只有一個(gè)進(jìn)程占用 CPU,但是系統(tǒng)中可能同時(shí)存在多個(gè)活動(dòng)的(等待執(zhí)行或繼續(xù)執(zhí)行的)進(jìn)程。
          一個(gè)稱為“程序計(jì)數(shù)器(program counter, pc)”的寄存器,指出當(dāng)前占用 CPU的進(jìn)程要執(zhí)行的下一條指令的位置。
          當(dāng)分給某個(gè)進(jìn)程的 CPU時(shí)間已經(jīng)用完,操作系統(tǒng)將該進(jìn)程相關(guān)的寄存器的值,保存到該進(jìn)程在進(jìn)程表中對(duì)應(yīng)的表項(xiàng)里面;把將要接替這個(gè)進(jìn)程占用 CPU的那個(gè)進(jìn)程的上下文,從進(jìn)程表中讀出,并更新相應(yīng)的寄存器(這個(gè)過(guò)程稱為“上下文交換(process context switch)”,實(shí)際的上下文交換需要涉及到更多的數(shù)據(jù),那和fork無(wú)關(guān),不再多說(shuō),主要要記住程序寄存器pc記錄了程序當(dāng)前已經(jīng)執(zhí)行到哪里,是進(jìn)程上下文的重要內(nèi)容,換出 CPU的進(jìn)程要保存這個(gè)寄存器的值,換入CPU的進(jìn)程,也要根據(jù)進(jìn)程表中保存的本進(jìn)程執(zhí)行上下文信息,更新這個(gè)寄存器)。
          好了,有這些概念打底,可以說(shuō)fork了。當(dāng)你的程序執(zhí)行到下面的語(yǔ)句:pid=fork(); 

          操作系統(tǒng)創(chuàng)建一個(gè)新的進(jìn)程(子進(jìn)程),并且在進(jìn)程表中相應(yīng)為它建立一個(gè)新的表項(xiàng)。新進(jìn)程和原有進(jìn)程的可執(zhí)行程序是同一個(gè)程序;上下文和數(shù)據(jù),絕大部分 就是原進(jìn)程(父進(jìn)程)的拷貝,但它們是兩個(gè)相互獨(dú)立的進(jìn)程!此時(shí)程序寄存器pc,在父、子進(jìn)程的上下文中都聲稱,這個(gè)進(jìn)程目前執(zhí)行到fork調(diào)用即將返回(此時(shí)子進(jìn)程不占有CPU,子進(jìn)程的pc不是真正保存在寄存器中,而是作為進(jìn)程上下文保存在進(jìn)程表中的對(duì)應(yīng)表項(xiàng)內(nèi))。問(wèn)題是怎么返回,在父子進(jìn)程中就分道揚(yáng)鑣。

          (假設(shè)父進(jìn)程一直占據(jù)CPU,實(shí)際情況很可能不一樣)父進(jìn)程繼續(xù)執(zhí)行,操作系統(tǒng)對(duì)fork的實(shí)現(xiàn),使這個(gè)調(diào)用在父進(jìn)程中返回剛剛創(chuàng)建的子進(jìn)程的pid(一個(gè)正整數(shù)),所以下面的swtich語(yǔ)句中執(zhí)行了default分支(case -1,case 0分支都不滿足)。所以輸出I am the parent process...

          子進(jìn)程在之后的某個(gè)時(shí)候得到調(diào)度,它的上下文被換入,占據(jù) CPU,操作系統(tǒng)對(duì)fork的實(shí)現(xiàn),使得子進(jìn)程中fork調(diào)用返回0,所以在這個(gè)進(jìn)程(注意這不是父進(jìn)程了哦,雖然是同一個(gè)程序,但是這是同一個(gè)程序的另外一次執(zhí)行,在操作系統(tǒng)中這次執(zhí)行是由另外一個(gè)進(jìn)程表示的,從執(zhí)行的角度說(shuō)和父進(jìn)程相互獨(dú)立)中pid=0。這個(gè)進(jìn)程繼續(xù)執(zhí)行的過(guò)程中,switch語(yǔ)句中 case -1不滿足,但是case 0是滿足。所以輸出I am the child process..

           

          程序的運(yùn)行結(jié)果(先輸出I am the parent process...,還是I am the parent process...)不可預(yù)見,與操作系統(tǒng)實(shí)際運(yùn)行情況有關(guān)!

          posted on 2012-07-26 11:51 姚先進(jìn) 閱讀(182) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
           
          主站蜘蛛池模板: 万全县| 奉贤区| 天水市| 玉门市| 平江县| 淮北市| 平安县| 沙田区| 冀州市| 南宁市| 汾阳市| 界首市| 泾阳县| 裕民县| 锡林郭勒盟| 宁城县| 三门峡市| 布拖县| 谢通门县| 桐梓县| 清远市| 南宁市| 将乐县| 青冈县| 南靖县| 山阴县| 陆良县| 上高县| 龙江县| 布拖县| 章丘市| 湟中县| 商水县| 渭南市| 云和县| 新泰市| 马尔康县| 岢岚县| 磐安县| 化州市| 娱乐|