最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時間:2016年06月08日 14:51:55   作者:sponge  
fork()函數(shù)在Linux下可以用于產(chǎn)生一個子進(jìn)程,這里我們挑選了兩個fork相關(guān)的面試題,來看一下Linux下C語言的fork()子進(jìn)程函數(shù)用法及相關(guān)問題解析

fork
fork()函數(shù)是linux下的一個系統(tǒng)調(diào)用,它的作用是產(chǎn)生一個子進(jìn)程,子進(jìn)程是當(dāng)前進(jìn)程的一個副本,它跟父進(jìn)程有一樣的虛存內(nèi)容,但也有一些不同點。
但是,值得注意的是,父進(jìn)程調(diào)用fork()后,fork()返回的是生成的子進(jìn)程(如果能順利生成的話)的ID。子進(jìn)程執(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) {
      // 主進(jìn)程
      sleep(5);
    } else if (pid == 0) {
      // 子進(jìn)程
      return 0;
    } else {
      fprintf(stderr, "fork error\n");
      return 2;
    }
  }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#include
int main(){
    fork();
    fork() && fork() || fork();
    fork();
}

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

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

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

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

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

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

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

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

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

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

相關(guān)文章

  • C++詳細(xì)講解引用類型

    C++詳細(xì)講解引用類型

    引用指的是對一個對象的引用。那么什么是對象?在c++中狹義的對象指的是用類,結(jié)構(gòu),聯(lián)合等復(fù)雜數(shù)據(jù)類型來聲明的變量,如?MyClass?myclass,CDialog?mydlg,等等
    2022-07-07
  • 詳解c++種gmock單元測試框架

    詳解c++種gmock單元測試框架

    這篇文章我們給大家分享了關(guān)于c++種gmock單元測試框架的相關(guān)知識點內(nèi)容,有興趣的朋友們學(xué)習(xí)下。
    2018-08-08
  • C++之談?wù)剺?gòu)造函數(shù)的初始化列表

    C++之談?wù)剺?gòu)造函數(shù)的初始化列表

    構(gòu)造函數(shù)主要作用在于創(chuàng)建對象時為對象的成員屬性賦值,構(gòu)造函數(shù)由編譯器自動調(diào)用,無須手動調(diào)用,這篇文章詳細(xì)介紹了構(gòu)造函數(shù)的初始化列表,文章中有詳細(xì)的示例代碼,感興趣的同學(xué)可以參考閱讀
    2023-04-04
  • C語言修煉之路數(shù)據(jù)類型悟正法 解析存儲定風(fēng)魔下篇

    C語言修煉之路數(shù)據(jù)類型悟正法 解析存儲定風(fēng)魔下篇

    使用編程語言進(jìn)行編程時,需要用到各種變量來存儲各種信息。變量保留的是它所存儲的值的內(nèi)存位置。這意味著,當(dāng)您創(chuàng)建一個變量時,就會在內(nèi)存中保留一些空間。您可能需要存儲各種數(shù)據(jù)類型的信息,操作系統(tǒng)會根據(jù)變量的數(shù)據(jù)類型,來分配內(nèi)存和決定在保留內(nèi)存中存儲什么
    2022-02-02
  • 學(xué)習(xí)C和C++的9點經(jīng)驗總結(jié)

    學(xué)習(xí)C和C++的9點經(jīng)驗總結(jié)

    本文給大家總結(jié)了一下我們在學(xué)習(xí)C和C++的時候的一些經(jīng)驗和需要注意的事項,希望能給大家一些幫助,少走些彎路
    2015-12-12
  • C++全排列中遞歸交換法實例詳解

    C++全排列中遞歸交換法實例詳解

    在本篇文章里小編給各位整理的是關(guān)于C++全排列中遞歸交換法實例內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2020-02-02
  • C++創(chuàng)建多線程的方法總結(jié)

    C++創(chuàng)建多線程的方法總結(jié)

    下個迭代有個任務(wù)很有趣,用大量的線程去訪問一個接口,直至其崩潰為止,這就需要多線程的知識,這也不是什么難事,本文總結(jié)一下C++中的多線程方法std、boost、pthread、windows?api,感興趣的朋友可以參考下
    2024-01-01
  • C語言實現(xiàn)簡單的飛機(jī)大戰(zhàn)游戲

    C語言實現(xiàn)簡單的飛機(jī)大戰(zhàn)游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)簡單的飛機(jī)大戰(zhàn)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C++實現(xiàn)Window環(huán)境聊天室功能

    C++實現(xiàn)Window環(huán)境聊天室功能

    這篇文章主要為大家詳細(xì)介紹了C++實現(xiàn)Window環(huán)境聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Dev C++編譯時運行報錯source file not compile問題

    Dev C++編譯時運行報錯source file not compile問題

    這篇文章主要介紹了Dev C++編譯時運行報錯source file not compile問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評論

丰镇市| 色达县| 朝阳市| 麟游县| 乃东县| 竹山县| 满城县| 宁明县| 江西省| 合水县| 公安县| 库伦旗| 利川市| 巫山县| 油尖旺区| 武平县| 彭水| 霞浦县| 鞍山市| 连云港市| 南雄市| 清徐县| 开平市| 桑日县| 广安市| 托里县| 鄂尔多斯市| 泉州市| 漳州市| 三门县| 陵水| 泽库县| 广德县| 收藏| 合山市| 汉沽区| 治县。| 阜康市| 南岸区| 林口县| 阳春市|