linux编程之fork及vfork

linux下的多线程编程中,创建进程主要用fock函数。使用该函数要包含头文件 fock()函数比较特殊,调用一次返回两次。如果执行成功,根据其返回值可以可以区别父子 进程,返回0表示在子进程中,如果在父进程中则返回子进程PID。出错返回-1,fock()创建 的子进程是父进程的副本,它将获得父进程数据段、BSS段、代码段,栈,堆等资源的副本。 但是父子进程间不共享这些存储空间。下面是一个fock()的实例!

#include<stdio.h>
#include<unistd.h>         
int main()
{
    int flag=0;
    int pid;
    printf("hello fluyy! ");
    if((pid=fork())==-1)
        perror("creat process");
    else if(pid==0)
    {
        flag++;
        printf("child process flag=%d\n",flag);
    }
    else
        printf("parent process flag=%d\n",flag);    
    return 0;
}

编译运行后的结果是:

hello fluyy parent process flag=0
hello fluyy child process flag=1

哇塞,奇葩啊!不是说子进程执行位置为fock()返回的位置吗?其之前的代码不执行啊!但是事实就在那里啊!hello fluyy的确执行了两次啊。这个问题让我困扰了好久。晚上问涛哥。完美解决啊。原来这和fock()函数执行之后会复制父进程几乎所有的信息,这当然包括缓冲区了。所以将printf语句改为printf(\"hello fluyy\n\");于是输出就正常了。hello fluyy果然就只输出了一次.

关于vfock()函数,这个函数和fork()有很大的不同。下面直接看一段代码

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

int main()
{
    int flag=0;
    int pid;
    printf("hello fluyy ");
    if((pid=vfork())==-1)
        perror("creat process");
    else if(pid==0)
    {
        flag++;
        printf("child process flag=%d\n",flag);
        exit(0);
    }
    else
        printf("parent process flag=%d\n",flag);
    return 0;
}


:::bash

hello fluyy child process flag=1
parent process flag=1

这样与第一段代码代码对比。可以发现这个地方hello fluyy 只输出一次。为什么?第二个父进程中的flag值受到了子进程的影响。Why?

其实这里就反映了fork()与vfork()的区别。

1.fork():子进程复制父进程的数据段 vfork():子进程与父进程共享数据段.所以子进程中flag++会影响父进程中的flag值。 同时vfork()只是共享数据,所以并没有复制之缓冲区内容。所以hello fluyy也就输出一次:)

2.fork():父子进程的执行次序不确定.vfork():保证子进程先运行,在调用exec或exit之前与父进程数据是共享的,在它调用exec或exit之后父进程才可能被调度运行。可以这样理解。在调用exec函数时,系统会为它分配空间。这时父进程将不再阻塞.

  1. 如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。 ps:如果上面的程序段二中exit(0)没有加上则会导致死循环直到进程号被分配完才会退出其实现在的vfork()是为了提高fork()后跟exec函数时的效率,减少不必要的复制才出现的。但是由于Copy-on-Write的使用,其实fork()的效率也相当的高。

大家可以google一下Copy-on-Write哈。 3. 如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。 ps:如果上面的程序段二中exit(0)没有加上则会导致死循环直到进程号被分配完才会退出其实现在的vfork()是为了提高fork()后跟exec函数时的效率,减少不必要的复制才出现的。但是由于Copy-on-Write的使用,其实fork()的效率也相当的高。

大家可以google一下Copy-on-Write哈。