fork與vfork詳解

一、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;
}

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章