a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 編程 > C > 正文

Linux下C語言的fork()子進程函數(shù)用法及相關(guān)問題解析

2020-01-26 14:33:46
字體:
供稿:網(wǎng)友

fork
fork()函數(shù)是linux下的一個系統(tǒng)調(diào)用,它的作用是產(chǎn)生一個子進程,子進程是當前進程的一個副本,它跟父進程有一樣的虛存內(nèi)容,但也有一些不同點。
但是,值得注意的是,父進程調(diào)用fork()后,fork()返回的是生成的子進程(如果能順利生成的話)的ID。子進程執(zhí)行的起點也是代碼中fork的位置,不同的是下面這段C語言代碼展示了fork()函數(shù)的使用方法:

// myfork.c#include <unistd.h>#include <stdio.h>int main(int argc, char **argv) {  while (1) {    pid_t pid = fork();    if (pid > 0) {      // 主進程      sleep(5);    } else if (pid == 0) {      // 子進程      return 0;    } else {      fprintf(stderr, "fork error/n");      return 2;    }  }}

調(diào)用fork()函數(shù)后,系統(tǒng)會將當前進程的絕大部分資源拷貝一份(其中的copy-on-write技術(shù)這里不詳述),該函數(shù)的返回值有三種情況,分別是:
1.大于0,表示當前進程為父進程,返回值是子進程號;
2.等于0,表示當前進程是子進程;
3.小于0(確切地說是等于-1),表示fork()調(diào)用失敗。

看兩個比較有意思的C語言題目。
 
第一題:計算下面代碼理論上總共打印了多少行:(網(wǎng)易2011筆試題)

#include#include#includeint main(){    int i;    for(i = 0; i<5; i++){        fork();        printf("%d/n",getpid());        fflush(stdout);    }}

問題解答:
這道問題并不難,最快的想法就是2+4+8+16+32,因為第一層的printf會有兩個進程打印,第二層會增加到4個,以此往下,就得出62行。
 
但我這里打算采用另外一種方法,一種更加直觀的方法,就是直接數(shù)出來,這樣會避免大腦短路,而且對下一題目有幫助。
 
要直接數(shù)出來也很簡單,只是有些繁瑣,因為每循環(huán)一次,都會打印一行并且產(chǎn)生一個子進程,子進程又會繼續(xù)循環(huán)打印并產(chǎn)生新的進程。我們可以在草稿紙上畫一棵樹,畫出每個進程的子進程以及循環(huán)次數(shù),如果你眼力夠好,腦子不容易亂,這種方法很快會讓你得到正確答案。但我恰好腦子不是能夠保證清醒的人,畫了三遍樹得到的都是錯誤答案。
 
隨后,我在紙上用了一種更簡單的數(shù)據(jù)結(jié)構(gòu)――隊列進行計算,并且順利得出了答案。我是這樣計算的:

首先,主進程會循環(huán)5次,則我們將5壓入到隊列中:

queue =" 5 ";sum = 0; //sum是總打印次數(shù)

主進程會循環(huán)5次,打印5行并且產(chǎn)生5個子進程,這5個子進程分別會打印5,4,3,2,1行,則我們將這5個數(shù)放入隊列,并將第一個5出隊列加入到sum中:

queue = " 5 4 3 2 1 ";sum = sum + 5;

這樣,我們再取隊列首元素,即5,他會打印5行,并且生成4個子進程,子進程的分別會打印4,3,2,1行,我們把這4個數(shù)放入到隊列中,并將第一個5出隊列加入到sum中:

queue = " 4 3 2 1 4 3 2 1";sum = sum + 5;

我們繼續(xù)重復上面的工作,取首元素4,他會打印4行,并且會聲稱3個子進程,子進程分別打印3,2,1行,重復上面的入隊列和出隊列操作:

queue = " 3 2 1 4 3 2 1 3 2 1 ";sum = sum + 4;

這樣,以此重復以上的操作,當遇到元素1的時候,只有出隊列而沒有入隊列的操作,因為只打印1行的子進程不會再循環(huán)產(chǎn)生新的子進程。最后,當隊列中不再有元素的時候,sum就是總共打印的行數(shù)。
 
這種方法的有點是你可以很輕松、很清醒的在紙上把隊列寫出來并算出答案,缺點是如果你加法不好,很容易算錯答案!
 

第二題:問下面的代碼執(zhí)行后總共產(chǎn)生了多少進程(不包括主進程)?(2009 EMC筆試)

#includeint main(){    fork();    fork() && fork() || fork();    fork();}

這個題目跟上一個對比起來就稍微有點難度了,因為你就算畫樹也有可能算錯!
 
我個人感覺這個題目考察兩方面的知識:1、開頭所講的fork()返回值;2、&&和||的運算。
 
讓我們現(xiàn)討論下&&和||的運算再來繼續(xù)討論這個題目。&&是“邏輯與”操作,如果兩個操作數(shù)有一個為0,則整個式子為0。標準C中規(guī)定,如果&&運算符的左操作數(shù)為0,則不計算右操作數(shù);如果左操作數(shù)為1,才計算右操作數(shù)。
與之類似,||操作符是“邏輯或”操作,標準C規(guī)定如果||運算符左操作數(shù)為1,則不計算右操作數(shù);如果左操作數(shù)為0,則計算右操作數(shù)。
 
繼續(xù)來看我們的題目,我們把題目中的5個fork()分別標記為A,B,C,D,E。則我們可以看到,主進程一共產(chǎn)生4個進程,分別產(chǎn)生在A,B,C,E位置上(B,C兩個fork()返回值都不是0,因此B&&C不為0,因此不計算D)。讓我們?nèi)匀徊捎蒙项}的算法,使用一個隊列:

首先,將主進程產(chǎn)生子進程的位置放到隊列中:

queue = " A B C E ";sum = 0;

我們從隊列中取首元素A,我們分析A處產(chǎn)生的進程,發(fā)現(xiàn)它會在B, C, E三處產(chǎn)生子進程,我們把這三個元素插入到隊列中,并將sum+1。

queue = " B C E B C E ";sum ++;

然后,我們從隊列中取出首元素B,B處產(chǎn)生的子進程稍稍不一樣,因為子進程中B所代表的fork()返回值為0,因此C得不到執(zhí)行,而D會得到執(zhí)行。因此,B處產(chǎn)生的子進程會執(zhí)行D, E,將這兩個元素送入隊列,sum++:

queue = " C E B C E D E ";sum ++;

下面,我們?nèi)∈自谻,分析發(fā)現(xiàn),C處產(chǎn)生的進程會執(zhí)行D, E,送入隊列并且sum++:

queue = " E B C E D E D E ";sum ++;

同上一題一樣,依次這樣執(zhí)行,遇到E則沒有元素入隊列,直到最后隊列為空,sum就是總共產(chǎn)生的進程個數(shù)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 一二三区字幕免费观看av | 91在线最新 | 99综合在线| www.99精品 | 久久久国产精品x99av | 亚洲成人中文字幕 | 永久精品 | 欧美成人精品在线观看 | 日韩久久久久久久久久久 | 久久97视频 | 免费看国产一级特黄aaaa大片 | 欧美一区不卡 | 日韩a视频| 中文字幕日韩欧美 | 日本精品免费 | 最近最新中文字幕 | 操一草 | 久久精品欧美一区二区三区不卡 | 99re视频在线播放 | 午夜激情电影在线 | 日本午夜一区二区 | 欧美日韩伊人 | 亚洲自拍一二三区 | 在线视频这里只有精品 | 国产一区二区三区在线 | 精品久久久久久久久久久久久久 | 国产夜夜夜 | 性做久久久久久久免费看 | 麻豆一区二区 | 日韩电影专区 | 免费黄色看片 | 国产精品毛片一区二区在线看 | 久久久蜜桃一区二区人 | 在线观看成人小视频 | 久草ab| 一区二区三区高清 | 91精品国产日韩91久久久久久 | 在线观看的黄色网址 | 国产视频一区二区三区四区 | 国产精品美女久久久久久久久久久 | www.国产 |