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

从中可以看书父进程是在等子进程执行完毕后才开始执行的。



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