zoukankan      html  css  js  c++  java
  • 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
    ",count,getpid());
       else
         printf("I am the parent process, the count is %d, my process ID is %d
    ",++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
    ", 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
    ", 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
    ", 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
    ", count);   /*创建进程之前*/
       if(!(child = vfork()))
        {  /*这里是子进程执行区*/
           int i;
           for(i = 0; i < 100; i++)
           {
              printf("This is son, The i is: %d
    ", i);
              if(i == 70)
                 exit(1);
           }
           printf("This is son, his pid is: %d and the count is: %d
    ", 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
    ", getpid(), count, child); 
        }
       return 0;
    }
    


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



  • 相关阅读:
    停滞的代码
    民兵葛二蛋大结局
    该开始BS了
    今天写出了第一个.NetBS应用
    读源码,仿照
    MVN,老天怎么回事?
    从哪里入手
    学习Java了
    工厂方法模式与简单工厂
    转:悟透JavaScript
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3170365.html
Copyright © 2011-2022 走看看