fork和vfork有什么区别

   自己在刚刚学习Linux进程的时候接触到了一个进程里边的第一个函数fork,最初接触的时候还是感觉比较稀奇的,后来发现也不过如此,之前还写过一个关于fork的博客,fork就是只调用一次,但是却有三个不同返回值的函数,可以通过它的返回值来判断是子进程还是父进程。但是fork和vfrok有什么区别的时候,我只是听说过vfrok并不是很了解两个有什么区别,今天就来总结一下,这两个函数到底有什么区别。

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

int main()
{
    int id=fork();
    if(id<0)
    {
        perror("fork error\n");
        return -1;
    }
    else
    {
        if(id==0)
        {
            printf("child pid:%d\n",getpid());
            sleep(3);
        }
        else
        {
            printf("parent pid:%d\n",getpid());
        }
    }
    return 0;
}

先写一个用fork创建进程的函数

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
int main()
{
   int id=vfork();
   if(id<0)
   {
       perror("vfork error\n");
   }
   else
   {
       if(id==0)
       {
           printf("child pid:%d\n",getpid());
           sleep(3);
           exit(1);
       }
       else
       {
           printf("parent pid:%d\n",getpid());           
       }
   }
   return 0;
}

再写一个vfork函数创建进程的程序。

先看一下这两个程序在执行瞬间程序结果的截图。

可以看出来vfork执行的瞬间只有一个子进程输出了信息,父进程没有输出信息,但是fork无论是父进程还是子进程都直接输出了结果。

   这里我们的子进程里边都有一个sleep(3)等了3秒之后vfork输出了父进程的语句。

和fork一样了。

所以第一点两个不一样的是1.fork在创建出来父进程和子进程之后会随机选择一个进程来执行,具体执行那个说不准,由调度器来决定,但是我试了几次之后发现都是先执行的父进程,不过定义里边没有确定的结果的。但vfork不一样,vfork是在创建出来子进程之后,必须先执行子进程,等子进程调用结束之后才回去调用父进程,所以在开始的时候没有输出父进程的语句,只有sleep(3)之后,子进程结束之后,才会调用父进程。

第二个特点:vfork里边子进程加了一句话exit(1)这句话在fork里边是没有的,我们去掉这句话再去执行vfrok程序。

会发现程序死不了,父进程没有变化但是子进程的id在不断的变化,说明子进程在不断的结束不断的创建。这是两个函数第二个区别vfork的子进程是不能使用return来退出的他必须使用exit如果使用return会回到调用vfork函数之前。

 

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

int val=100;
int main()
{
    int id=fork();
    if(id<0)
    {
        perror("fork error\n");
        return -1;
    }
    else
    {
        if(id==0)
        {
            val=200;
            printf("child pid:%d val:%d ad:%p\n",getpid(),val,&val);
            sleep(3);
        }
        else
        {
            printf("parent pid:%d val:%d ad:%p\n",getpid(),val,&val);
        }
    }
    return 0;
}

 

这里我们创建一个变量,val然后在子进程里边对它进行修改,然后在子进程和父进程里边分别打印出它的值和地址

fork里边父进程和子进程虽然地址是一样的,但是子进程里边的值修改不会改变父进程里边的值。这里的地址是我们所说的虚拟地址,并不是变量实际的地址。所以打印出来了地址一样,但是内容不一样的情况。

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
int val=100;
int main()
{
   int id=vfork();
   if(id<0)
   {
       perror("vfork error\n");
   }
   else
   {
       if(id==0)
       {
           val=200;
           printf("child pid:%d val:%d ad:%p\n",getpid(),val,&val);
           sleep(3);
           exit(1);
       }
       else
       {
           printf("parent pid:%d val:%d ad:%p\n",getpid(),val,&val);           
       }
   }
   return 0;
}

我们再看vfork

这里子进程里边的修改影响到了父进程,自然地址也是一样的。

这就是fork和vfork的第三个不同,fork函数里边,父进程和子进程是不同的地址空间,子进程的操作不会对父进程起到影响,但是vfork则不同,在调用exit函数之前子进程是在父进程的空间里边运行的,他是可以修改父进程的数据段,堆和栈的。

  在最初的时候设计了fork函数,他在创建子进程的时候会创建一个新的地址空间,并且把父进程的情况都给拷贝过去,但是往往来说人们都是运用进程替换把子进程替换成了其他程序,所以这个拷贝的过程就完全浪费了,所以fork函数就变成了用来创建新进程的函数,vfork就是在某种程度上代替了最初的fork。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值