函数fork和vfork

一.函数fork

一个现有的进程可以调用fork函数创建一个新的进程。

#include <unistd.h>
pid_t fork(void);

返回值:子进程返回0,父进程返回子进程ID;若出错,返回-1 。

fork函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是新建子进程的进程ID。

将子进程ID返回给父进程的原因是:因为一个进程的子进程可以有多个,并且没有一个函数使一个进程可以获得其所有子进程的进程ID。

fork使子进程得到返回值0的理由是:一个进程只会有一个父进程,所以子进程总是可以调用getppid以获得其父进程的进程ID。

子进程和父进程继续执行fork调用之后的指令。子进程是附近成的副本。子进程获得附近成数据空间,堆和栈的副本。下面一个例子可以看出子进程对变量的修改不影响父进程中该变量的值。

#include "apue.h"
//#include "error.h"
using namespace std;

int globvar=6;   //external variable in initialized data
char buf[]="a write to stdout\n";

int main()
{
  int var;    //automatic value on the stack
  pid_t pid;
  var=88;
  if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1)
    printf("write error");
  printf("before fork\n");          //we don't flush stdout

  if((pid=fork())<0)
    {
      printf("fork error");
    }
  else if(pid==0)    //子进程
    {
      globvar++;
      var++;
    }
  else                 //父进程,使自己休眠2s,从而让子进程进行
    sleep(2);
  printf("pid=%ld,glob=%d,var=%d\n",(long)getpid,globvar,var);
  exit(0);
}

执行此程序得到:


在fork后父进程先执行还是子进程先执行是不确定的。


二.函数vfork

vfork函数的调用序列和返回值与fork相同,但两者的语义不同。

vfork函数用于创建一个新进程,该进程的目的是exec一个新程序。vfork与fork一样都创建一个子进程,但是vfork不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec(或exit),于是也就不会引用该地址空间。不过在调用exec或exit之前,它会在父进程的空间中运行。

vfork和fork之间的另一个区别是:vfork保证子进程先运行,在它调用exec或exit之后父进程才能被调度执行。(如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。)

下面的程序不再需要让父进程调用sleep,因为我们可以保证,在子进程调用exec或exit之前,内核会使父进程处于休眠状态。

#include "apue.h"
#include "myerror.h"
using namespace std;

int globvar=6;   //external variable in initialized data
char buf[]="a write to stdout\n";

int main()
{
  int var;    //automatic value on the stack
  pid_t pid;
  var=88;
  //if(write(STDOUT_FILENO,buf,sizeof(buf)-1)!=sizeof(buf)-1)
  //printf("write error");
  printf("before fork\n");          //we don't flush stdout

  if((pid=fork())<0)
    {
      //printf("fork error");
      err_sys("vfork error");
    }
  else if(pid==0)
    {
      globvar++;
      var++;
      _exit(0);
    }
  printf("pid=%ld,glob=%d,var=%d\n",(long)getpid,globvar,var);
  exit(0);
}

注意:子进程对变量作增1操作,结果改变了父进程中的变量值,这是因为子进程在父进程的地址空间中进行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值