fork與vfork詳解

weixin_33941350發表於2013-07-03

一、fork函式

要建立一個程式,最基本的系統呼叫是fork,系統呼叫fork用於派生一個程式,函式原型如下: pid_t fork(void)  若成功,父程式中返回子程式ID,子程式中返回0,若出錯返回-1;fork()系統呼叫的作用是複製一個程式,當一個程式呼叫它,完成個就出現兩個幾乎一摸一樣的程式,新程式是子程式,原來的程式是父程式。子程式是父程式的一個拷貝,子程式從父程式那裡得到了程式碼段和資料段的拷貝。Fork函式呼叫一次,但返回兩次,兩次返回的區別是子程式的返回值是0,父程式的返回值是子程式返回值的程式ID。Fork返回後,子程式和父程式都從呼叫fork函式的下一條語句開始執行。

程式一是fork呼叫:

 

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main (void)
{
int count = 0;
pid_t pid;        /*此時僅有一個程式*/
pid = fork();      /*此時已經有兩個程式在同時執行*/
if(pid < 0)
 {
   printf("error in fork!");
        exit(1);    /* fork出錯退出*/
     }
else if(pid==0)
  printf("I am the child process, the count is %d, my process ID is %d\n",count,getpid());
   else
     printf("I am the parent process, the count is %d, my process ID is %d\n",++count,getpid());
   return 0;
}


 

必須瞭解一個概念:在語句pid = fork();之前,只有一個程式在執行這段程式碼,該語句之後,就變成兩個程式在執行了,且二者程式碼部分完全相同,將要執行的下一條語句都是 if(pid<0)。

 

Fork函式的奇妙之處是僅僅被呼叫一次,卻返回了兩次,可能有三種取值:

1,在父程式中,fork返回新建立子程式的ID

2,在子程式中,fork返回0

3,出現錯誤時,返回負值

二、linux下另一個建立程式的方式是vfork,原型如下:pid_t vfork(void);

若成功,父程式中返回子程式ID,子程式中返回0,若出錯返回-1;fork與vfork是有區別的,fork要拷貝父程式的資料段,而vfork不需要完全拷貝父程式的資料段,在子程式沒有呼叫exec或者exit函式之前,子程式會與父程式共享資料段。在fork中子程式與父程式的執行順序不確定,而在vfork中,子程式先執行,父程式掛起,直到子程式呼叫了exec或者exit函式,父程式才被執行。

程式二說明了vfork建立後父子程式是共享資料段的。

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main (void)
{
   int count = 1;
   int child;
   printf("Before create son, the father's count is:%d\n", count);  /*建立程式之前*/
   child = vfork();      /*此時已經有兩個程式在同時執行*/
   if(child < 0)
     {
        printf("error in vfork!");
        exit(1);    /* fork出錯退出*/
      }
   if(child==0)     /*子程式*/
     {
        printf("This is son, his pid is: %d and the count is: %d\n", getpid(), ++count);
        exit(1);
     } 
   else            /*父程式*/
     {
        printf("After son, This is father, his pid is: %d and the count is: %d, and the child is: %d\n", getpid(), count, child); 
     }
   return 0;
}


在子程式中修改了count值,在父程式中輸出count時是子程式修改後的值,這說明父程式和子程式是共享count,也就是二者是共享記憶體區的。

程式三說明由vfork創造出來的子程式是會導致父程式掛起,直到子程式執行xec或者exit函式才會喚醒父程式

 

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main (void)
{
   int count = 1; 
   int child;
   printf("Before create son, the father's count is:%d\n", count);   /*建立程式之前*/
   if(!(child = vfork()))
    {  /*這裡是子程式執行區*/
       int i;
       for(i = 0; i < 100; i++)
       {
          printf("This is son, The i is: %d\n", i);
          if(i == 70)
             exit(1);
       }
       printf("This is son, his pid is: %d and the count is: %d\n", getpid(), ++count);
       exit(1);  /*子程式退出*/
    }
   else
    {  /*父程式執行區*/
         printf("After son, This is father, his pid is: %d and the count is: %d, and the child is: %d\n", getpid(), count, child); 
    }
   return 0;
}


 

從中可以看書父程式是在等子程式執行完畢後才開始執行的。



相關文章