fork 与 vfork 的区别

目录

fork 与 vfork:

头文件:

函数原型

函数功能

fork

返回值:

总结:

vfork

返回值

总结


fork 与 vfork:

头文件:

#include<sys/types.h>
#include<unistd.h>

函数原型

fork

pid_t fork(void);

vfork

pid_t vfork(void);

函数功能

fork() 函数和 vfork() 函数一样都是在已有的进程中创建一个新的进程。

fork

返回值:

         -1: 函数调用失败,创建子进程失败,且设置errno 
         0 : 子进程
        >0: 在父进程中,且返回值为创建的子进程的进程号

总结:

        1.子进程拷贝父进程的数据段,代码段完全复制父进程的资源。这样得到的子进程独立于父进程,具有良好的并发性。

        2.fork作用创建子进程,子进程和父进程并行执行,fork创建的子进程和父进程执行的顺序不确定——统一由cpu调度
        3.子进程的执行是从fork的下一条语句开始执行,直到子进程退出为止

        4.缺点:使用fork创建一个进程时,子进程需要将父进程几乎每种资源都复制,所以fork是一个开销很大的系统调用,这些开销并不是所有情况都需要的。比如fork一个进程后,立即调用exec执行另一个应用程序,那么fork过程中子进程对父进程地址空间的复制将是一个多余的过程。

例:

#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
	pid_t pid = fork();
	if(pid == -1)
	{
		perror("fork");	//创建失败打印原因
		return -1;
	}
	if(pid == 0)		//子进程
	{
		printf("child process pid: %d,parent process pid: %d\n",getpid(),getppid());
	}    //getpid返回当前进程标识,getppid返回父进程标识
	else                //父进程
	{
		printf("parent pid: %d, parent process pid: %d\n",getpid(),getppid());	
	}
	return 0;
}

运行结果

parent pid: 2834, parent process pid: 2642           先打印父进程    父进程的进程号2834    
child process pid: 2835,parent process pid: 2834       在打印子进程    子进程的父进程号2834

      有两个打印结果是因为fork在创建子进程后,子进程和父进程并行执行,只不过fork创建的子进程和父进程执行的顺序不确定。(相当于子进程拷贝了父进程 pid_t pid = fork(); 以下的代码段,所以子进程中同样会执行后面的语句,由于子进程中pid == 0为真,所以执行了if语句的内容)。

vfork

返回值

        成功:子进程中返回 0,父进程中返回子进程 ID。

        失败:返回 -1。

总结

        1.使用vfork创建一个子进程时,操作系统并将父进程的地址空间完全复制到子进程,子进程共享父进程的地址空间,子进程对该地址空间中任何数据的修改同样为父进程所见。

        2.使用vfork创建一个子进程时,vfork保证子进程先运行,当他调用exec或exit之后,父进程才可能被调读运行。如果在调用exec或exit之前子进程要依赖父进程的某个行为,就会导致死锁

        3.优点:vfork不会不会像fork一样拷贝父进程的地址空间,这大大减小了系统的开销。

#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>

int main(int argc, char *argv[])
{
    pid_t pid;
    int a = 0;
    pid = vfork();
    if(pid<0)
	{
        perror("vfork");    //创建打印失败原因
		return -1;
	}
    else if(pid == 0)	//子进程
    {
        a++;
        printf("a = %d\n",a);
        printf("Child process,ID is %d\n",getpid());
       _exit(0);    //结束子进程
    }
    else        //父进程
    {
        a++;
        printf("a = %d\n",a);
        printf("Parent process,ID is %d\n",getpid());
    }
    return 0;
}

运行结果

a = 1
Child process,ID is 3033
a = 2
Parent process,ID is 3032

_exit(0);使得子进程退出,父进程执行,这样else 后的语句就会被父进程执行,又因在子进程调用exec 或exit之前与父进程数据是共享的,所以子进程退出后把父进程的数据段a改成1 了,子进程退出后,父进程又执行,最终就将a变成了2;如果没有_exit(0)的话,子进程没有调用exec 或exit,所以父进程是不可能执行的。

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值