麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 服務(wù)器 > Linux服務(wù)器 > 正文

淺談Linux vfork與fork簡(jiǎn)單對(duì)比分析

2024-09-05 23:04:23
字體:
供稿:網(wǎng)友

本文分享了Linux vfork與fork簡(jiǎn)單對(duì)比分析,分享給大家,具體如下:

fork相關(guān)問題:

一、fork基礎(chǔ)了解

fork作用為創(chuàng)建一個(gè)子進(jìn)程,在使用了fork命令后,內(nèi)核會(huì)分配新的內(nèi)存塊和數(shù)據(jù)結(jié)構(gòu)給子進(jìn)程,并且將父進(jìn)程的部分?jǐn)?shù)據(jù)結(jié)構(gòu)內(nèi)容拷貝到子進(jìn)程,最后再將子進(jìn)程添加到系統(tǒng)進(jìn)程列表中,添加完成后fork返回,開始調(diào)度。

頭文件:#include < unistd.h >

函數(shù)原型:pid_t fork( )

返回值:返回值大于0則當(dāng)前進(jìn)程為父進(jìn)程,等于0代表為子進(jìn)程,小于零代表創(chuàng)建子進(jìn)程失敗。

通過一個(gè)例子來了解:

  #include <stdio.h>  #include <unistd.h>        int main()  {    int tmp = 5;    pid_t res = fork();    if(res < 0){     //fork失敗     perror("fork");   }else if(res == 0){     //該進(jìn)程為子進(jìn)程     printf("im child[%d],fasther is %d,tmp is %d./n",getpid(),getppid(),tmp++);   }else{     //該進(jìn)程為父進(jìn)程     printf("im father[%d],tmp is %d./n",getpid(),tmp++);   }   printf("tmp = %d/n",tmp);   return 0; }     

運(yùn)行結(jié)果:

im father[3128],tmp is 5.
tmp = 6
im child[3129],fasther is 1,tmp is 5.
tmp = 6

相關(guān)問題小結(jié):

通過結(jié)果很明顯的能看出本次調(diào)用中,先執(zhí)行父進(jìn)程,對(duì)應(yīng)pid為3128,在父進(jìn)程中tmp++,所以輸出為6;關(guān)鍵問題在于子進(jìn)程,有兩個(gè)關(guān)鍵點(diǎn)。

①為什么結(jié)果中子進(jìn)程父親pid為1:通過輸出我們能看出父進(jìn)程先執(zhí)行完成后才執(zhí)行的子進(jìn)程,也就是說當(dāng)子進(jìn)程執(zhí)行時(shí)父進(jìn)程已結(jié)束,此時(shí)該子進(jìn)程相當(dāng)于一個(gè)孤兒進(jìn)程,被pid為1也就是Init進(jìn)程所管理,所以子進(jìn)程的ppid為1;

②為什么子進(jìn)程最后輸出tmp值還為6: fork進(jìn)程采用的是寫時(shí)拷貝,父子進(jìn)程一開始共享一片內(nèi)存區(qū)域,但是只有有一方要對(duì)數(shù)據(jù)進(jìn)行修改,則再開辟一塊空間,防止相互修改影響。所以在上述代碼中,雖說是一個(gè)tmp,其實(shí)內(nèi)存中各自保留了一份值。

二、關(guān)于fork過程中寫時(shí)拷貝:

Linux,vfork與fork,vfork,fork,區(qū)別

Linux,vfork與fork,vfork,fork,區(qū)別

這下就不難看出,父子進(jìn)程數(shù)據(jù)段和代碼段開始時(shí)是共享一塊對(duì)應(yīng)的內(nèi)存,當(dāng)一方嘗試寫入時(shí),便產(chǎn)生了寫時(shí)拷貝。需要注意的是:fork之前,父進(jìn)程獨(dú)立執(zhí)行,fork之后,父子兩個(gè)執(zhí)行流分別執(zhí)行,至于誰先執(zhí)行,由調(diào)度器決定。可通過下面例子很明顯的看出是從fork之后才分別執(zhí)行。

  #include <stdio.h>  #include <unistd.h>      int main()  {    int tmp = 5;    printf("There is fork before/n");    pid_t res = fork();   if(res < 0){     //fork失敗     perror("fork");   }else if(res == 0){     //該進(jìn)程為子進(jìn)程     printf("im child[%d],tmp is %d./n",getpid(),tmp++);   }else{     //該進(jìn)程為父進(jìn)程     printf("im father[%d],tmp is %d./n",getpid(),tmp++);   }   printf("tmp = %d/n",tmp);   return 0; }

輸出結(jié)果:

There is fork before

im father[3625],tmp is 5.

tmp = 6

im child[3626],tmp is 5.

tmp = 6

三、fork調(diào)用失敗的原因:

①系統(tǒng)中已經(jīng)存在太多進(jìn)程,無法再創(chuàng)建新的進(jìn)程。可通過ulimit -a命令查看當(dāng)前所有的資源限制。

②內(nèi)存不足,由于開辟每個(gè)新的進(jìn)程都要分配一個(gè)PCB,并為新進(jìn)程分配資源,內(nèi)存都不足也就別提還想著再創(chuàng)建進(jìn)程了。

vfork相關(guān)問題:

一、vfork基礎(chǔ)了解

<1>vfork創(chuàng)建新進(jìn)程的主要目的在于用exec函數(shù)執(zhí)行另外的程序,實(shí)際上,在沒調(diào)用exec或_exit之前子進(jìn)程與父進(jìn)程共享數(shù)據(jù)段。在vfork調(diào)用中,子進(jìn)程先運(yùn)行,父進(jìn)程掛起,直到子進(jìn)程調(diào)用exec或_exit,在這以后,父子進(jìn)程的執(zhí)行順序不再有限制。

頭文件:#include < unistd.h >

函數(shù)原型:pid_t vfork( )

返回值:返回值大于0則當(dāng)前進(jìn)程為父進(jìn)程,等于0代表為子進(jìn)程,小于零代表創(chuàng)建子進(jìn)程失敗。

通過一個(gè)例子來了解:

 #include <stdio.h>  #include <unistd.h>    int tmp = 3;    int main()  {    pid_t res = vfork();    if(res < 0){     perror("vfork");     _exit();   }else if(res == 0){    tmp = 10; printf("child res = %d/n",tmp);     _exit(0);   }else{     printf("father res = %d/n",tmp);   }    return 0; }

輸出結(jié)果:

child res = 10

father res = 10

結(jié)果分析:正如上面所說的,子進(jìn)程直接公用父進(jìn)程的頁表,改變子進(jìn)程的數(shù)據(jù)也會(huì)影響到父進(jìn)程。

Linux,vfork與fork,vfork,fork,區(qū)別

<2>vfork用處:

vfork()跟fork()類似,都是創(chuàng)建一個(gè)子進(jìn)程,這兩個(gè)函數(shù)的的返回值也具有相同的含義。但是vfork()創(chuàng)建的子進(jìn)程基本上只能做一件事,那就是立即調(diào)用_exit()函數(shù)或者exec函數(shù)族成員,調(diào)用任何其它函數(shù)(包括exit())、修改任何數(shù)據(jù)(除了保存vfork()返回值的那個(gè)變量)、執(zhí)行任何其它語句(包括return)都是不應(yīng)該的。更需要注意的是:調(diào)用vfork()之后,父進(jìn)程會(huì)一直阻塞,直到子進(jìn)程調(diào)用_exit()終止,或者調(diào)用exec函數(shù)族成員。

<3>為什么只能用_exit退出:

exit()是對(duì)_exit()的封裝,它自己在調(diào)用_exit()前會(huì)做很多清理工作,其中包括刷新并關(guān)閉當(dāng)前進(jìn)程使用的流緩沖(比如stdio.h里面的printf等),由于vfork()的子進(jìn)程完全共享了父進(jìn)程地址空間,子進(jìn)程里面的流也是共享的父進(jìn)程的流,所以子進(jìn)程里面是不能做這些事的。直接return就更不行了,子進(jìn)程return以后,會(huì)從當(dāng)前函數(shù)的外部調(diào)用點(diǎn)后面繼續(xù)執(zhí)行,這后面子進(jìn)程可能將會(huì)執(zhí)行很多語句,結(jié)果就沒法預(yù)料了。在man手冊(cè)中也強(qiáng)調(diào)了這一點(diǎn),必須使用_exit退出。

fork與vfork的區(qū)別

1.vfork保證子進(jìn)程先運(yùn)行,在它調(diào)用exec或exit之后父進(jìn)程才可能被調(diào)度運(yùn)行。如果在調(diào)用這兩個(gè)函數(shù)之前子進(jìn)程依賴于父進(jìn)程的進(jìn)一步動(dòng)作,則會(huì)導(dǎo)致死鎖。

2.fork要拷貝父進(jìn)程的進(jìn)程環(huán)境;而vfork則不需要完全拷貝父進(jìn)程的進(jìn)程環(huán)境,在子進(jìn)程沒有調(diào)用exec和exit之前,子進(jìn)程與父進(jìn)程共享進(jìn)程環(huán)境,相當(dāng)于線程的概念,此時(shí)父進(jìn)程阻塞等待。

為什么會(huì)有vfork呢?

因?yàn)橐郧暗膄ork當(dāng)它創(chuàng)建一個(gè)子進(jìn)程時(shí),將會(huì)創(chuàng)建一個(gè)新的地址空間,并且拷貝父進(jìn)程的資源,然后將會(huì)有兩種行為:

1.執(zhí)行從父進(jìn)程那里拷貝過來的代碼段

2.調(diào)用一個(gè)exec執(zhí)行一個(gè)新的代碼段

當(dāng)進(jìn)程調(diào)用exec函數(shù)時(shí),一個(gè)新程序替換了當(dāng)前進(jìn)程的正文,數(shù)據(jù),堆和棧段。這樣,前面的拷貝工作就是白費(fèi)力氣了,這種情況下,聰明的人就想出了vfork。vfork并不復(fù)制父進(jìn)程的進(jìn)程環(huán)境,子進(jìn)程在父進(jìn)程的地址空間中運(yùn)行,所以子進(jìn)程不能進(jìn)行寫操作,并且在兒子“霸占”著老子的房子時(shí)候,要委屈老子一下了,讓他在外面歇著(阻塞),一旦兒子執(zhí)行了exec或者exit后,相當(dāng)于兒子買了自己的房子了,這時(shí)候就相當(dāng)于分家了。

因此,如果創(chuàng)建子進(jìn)程是為了調(diào)用exec執(zhí)行一個(gè)新的程序的時(shí)候,就應(yīng)該使用vfork

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 久久九九热re6这里有精品 | 一级黄色毛片子 | 亚洲码无人客一区二区三区 | 欧美性生活久久久 | 国产超碰人人爽人人做人人爱 | av免费在线观看免费 | 久草热久草视频 | 久草中文网 | 九色 在线 | 日韩黄色片免费看 | 精国产品一区二区三区四季综 | 国产精品麻豆一区二区三区 | 免费在线观看毛片视频 | 亚洲精品永久视频 | 婷婷亚洲一区二区三区 | 毛片一区二区三区四区 | 欧美一级黄色免费 | 精品国产一区二区三区久久久蜜月 | 欧美日韩一区,二区,三区,久久精品 | 精品国产一区二区三区四区在线 | 精品国产三级a | 欧洲精品色 | 天天操很很操 | 51色视频| 国产精品野外av久久久 | 免费国产一区二区视频 | 一级黄色性感片 | 美女亚洲综合 | 国产18成人免费视频 | 717影院理论午夜伦八戒秦先生 | 福利在线小视频 | 精品国产91久久久久久久 | 久久久久久久99 | 久久久久免费精品 | 久久成人亚洲 | qyl在线视频精品免费观看 | 久久毛片免费 | 色综合激情| 久久久久亚洲美女啪啪 | 久久老司机精品视频 | 欧美亚洲一区二区三区四区 |