天天看點

fork函數和vfork函數差別總結 及提問求解

fork和vfork兩個都是子程序建立函數,這裡總結兩點常用差別(還有些差別比較雜,不想提~):

1.執行順序:fork子程序與父程序都要運作(順序、進度随緣,核心說了算),而vfork一定是子程序先運作,父程序後運作;

2.虛拟記憶體:fork子程序拷貝父程序記憶體空間,vfork子程序共享父程序記憶體空間;

    這裡注意:使用帶緩存的輸入輸出函數時,fork的子程序會拷貝父程序的緩存,而vfork的子程序會共享父程序的緩存,具體有什麼影響後面分析;

簡單介紹下兩個函數

fork()和vfork()函數:函數調用一次傳回兩次,對子程序(0)、對父程序(>0、子程序id)各傳回一次

fork調用以後就有兩個程序了,後續的代碼由兩個程序各自執行一遍;

第一個執行順序的差別很好了解,vfork子程序執行完後續代碼後,父子程序才開始運作,不在贅述;

第二個虛拟記憶體的差別,帶緩沖檔案操作函數的簡單代碼,一個用fork,一個用vfork:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main()
{
   /*帶緩存功能函數操作檔案*/
   FILE *fp=fopen("aaa.txt","w");
   fprintf(fp,"pid%d,",getpid());     //父程序寫入
   
   fork();                            //建立子程序
   //vfork();

   fprintf(fp,"pid%d,",getpid());     //父、子程序都要寫入
   fclose(fp);
   exit(0);
}
           

fork對應的aaa.txt寫入結果:pid3553,pid3553,pid3553,pid3554,

vfork對應的aaa.txt寫入結果:pid3560,pid3561

分析{

這裡有不得不說exit除了退出外另一功能——重新整理緩存。

fork:也就是說,父程序退出時将兩次自己的pid寫入檔案,而fork建立子程序會拷貝父程序的緩存空間(一個父pid),在子程序運作到exit退出的時候,将先拷貝的父程序pid和後寫入的自己pid(都在緩存空間)一起寫入檔案,一共有四個pid。

vfork:父程序将自己pid寫入緩存,vfork子程序共享了父程序的緩存,子程序再往緩存中寫入自己的pid,子程序運作退出時寫入了父和自己的pid到檔案;到父程序運作,發現緩存裡面已經沒東西了,那就隻寫自己的pid,這個時候,發現在記憶體空間,打開的檔案被兒子關上了,隻能寫個寂寞,是以vfork裡隻有兩個pid。

}

附上帶緩沖函數檔案操作的fork改進版本

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main()
{
   /*帶緩存功能函數操作檔案*/
   FILE *fp=fopen("aaa.txt","w");
   fprintf(fp,"pid%d,",getpid());     //父程序寫入
   
   fflush(fp);                        //重新整理緩沖區
   fork();                            //建立子程序

   fprintf(fp,"pid%d,",getpid());     //父、子程序都要寫入
   fclose(fp);
   exit(0);
}
           

fork對應的aaa.txt寫入結果:pid3553,pid3553,pid3554,

可控且達到預期!!

第二個虛拟記憶體相關,不帶緩沖檔案操作函數的簡單代碼,一個用fork,一個用vfork:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
   /*不帶緩存功能函數操作檔案*/
   int fp=open("aaa.txt",O_WRONLY|O_CREAT);
   
   char *s="hello!";
   ssize_t size = strlen(s)*sizeof(char);
   
   write(fp,s,size);                              //父程序寫入
   
   fork()
   //vfork();                                     //建立子程序
 
   write(fp,s,size);                              //父、子程序都要寫入
   close(fp);
   
   exit(0);
}
           

fork對應的aaa.txt寫入結果:hello!hello!hello!

vfork對應的aaa.txt寫入結果:hello!hello!hello!

都是三個hello?

分析{

不帶緩存就不分析緩存空間了,但為什麼vfork時子程序已經close檔案了,另一個程序還可以往裡面寫入?

答案是我也不知道,求大神指點!!!!

}

附帶一個例子:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

int main()
{
   /*不帶緩存功能函數操作檔案*/
   int fp=open("aaa.txt",O_WRONLY|O_CREAT);
   
   char *s="hello!";
   ssize_t size = strlen(s)*sizeof(char);
   
   write(fp,s,size);                              //父程序寫入
   
   fork()
   //vfork();                                     //建立子程序
 
   write(fp,s,size);                              //父、子程序都要寫入
   close(fp);
   write(fp,s,size);                              //父、子程序都要寫入  

   exit(0);
}
           

fork對應的aaa.txt寫入結果:hello!hello!hello!

vfork對應的aaa.txt寫入結果:hello!hello!hello!

這個輸出結果居然也是三個hello?

這誰想得通,求指點~~~~

繼續閱讀