linux的fork和vfork

2023-05-16

fork和vfork

区别

fork函数和vfork函数都可以用来创建一个子进程。他们有什么区别呢?

首先是fork:

  • 内核会给子进程分配虚拟内存空间和id,但不会分配物理内存
  • 子进程一开始是共享父进程的物理空间
  • 子进程写入数据后内核会给它分配物理内存

然后是vfork:

  • 子进程共享父进程的虚拟地址空间

下面通过两个图来分别展示他们的特点:

  1. 进程P1通过fork函数创建一个子进程P2:
    1234

分析:
如上图所示,P1创建了一个子进程P2,内核为这个子进程分配了虚拟内存空间,并且把P1的正文段、数据段、堆、栈的虚拟空间的内容直接复制到子进程相应的虚拟空间上;但是内核并没有给子进程分配物理空间,所以子进程P2的虚拟空间是直接指向了父进程P1的物理空间。

那问题来了,子进程什么时候可以拥有自己的物理空间呢?
当子进程尝试修改数据段或堆栈中的数据时,内核会通过写时拷贝技术给子进程分配新的物理空间,并把父进程相应的段的数据拷贝过来。

为什么要使用写时拷贝技术?
因为大多数情况下,创建子进程之后都是让它去执行一个新程序;如果把父进程
的数据直接拷贝过来但是又不使用就会造成浪费:浪费cpu资源、占用空间。

  1. 进程P1通过vfork函数创建一个子进程P2:
    22234567

从上图可以看出,内核连虚拟内存空间都不分配,子进程是直接共享父进程的虚拟内存空间,所以也就共享父进程的数据。

特点

我们汇总一下fork函数和vfork函数的特点

函数特点
fork1、使用写时拷贝技术 2、子进程创建之后父子进程执行的顺序具有不确定性
vfork1、直接共享父进程的地址空间和数据 2、子进程创建之后可以确定子进程先执行,当它调用exit退出或者调用exec函数执行新程序后父进程才可能被调度

简单代码示例

fork示例

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

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


int main(int argc, char **argv)
{
	int count = 0;
	pid_t pid;
	int wstatus;
	char *p = NULL;

	pid = fork();
	if(pid < 0)
	{
		printf("creat a child fail");
		return -1;
	}
	else if(pid == 0)
	{
		count++;
		printf("child's id:%d,[%p]count:%d\n", (int)getpid(),&count,count);
		exit(0);
	}
	else
	{
		printf("father's id:%d,[%p]count:%d\n",(int)getpid(), &count, count);
		
		pid = waitpid(pid, &wstatus, 0);
		if((int)pid < 0)
		{
			printf("wait child fail\n");
			return -1;
		}

		exit(0);
	}
}

运行结果如下:

zzc@zzc-virtual-machine:~/share/example/process$ ./p3
father's id:2447,[0x7fff152556bc]count:0
child's id:2448,[0x7fff152556bc]count:1

分析:由于父子进程count变量的地址相同,所以可以确定子进程复制了父进程的虚拟空间;而且count的值不同,可以确定子进程通过写时拷贝拥有了自己的物理空间数据。
另外,父子进程的执行顺序具有不确定性,从实际测试来看一般是父进程先执行。

vfork示例

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



int main(int argc, char **argv)
{
	int count = 0;
	pid_t pid;

	pid = vfork();
	if(pid < 0)
	{
		printf("creat a child fail");
		return -1;
	}
	else if(pid == 0)
	{
		count++;
		printf("child's id:%d,[%p]count:%d\n", (int)getpid(),&count,count);
		
		if(execlp("ps", "ps", "-t", NULL)<0)
		{
			perror("exec a new program fail");
			exit(1);
		}
	}
	else
	{
		printf("father's id:%d,[%p]count:%d\n",(int)getpid(), &count, count);
	}
}

运行结果如下:

zzc@zzc-virtual-machine:~/share/example/process$ ./p1
child's id:2557,[0x7ffdaa834c80]count:1
father's id:2556,[0x7ffdaa834c80]count:1
zzc@zzc-virtual-machine:~/share/example/process$     PID TTY      STAT   TIME COMMAND
   1650 pts/0    Ss+    0:00 -bash
   2557 pts/0    R      0:00 ps -t

zzc@zzc-virtual-machine:~/share/example/process$ 

分析:
从结果来看,可以确定子进程先执行,父进程后执行;count变量的地址和值都相同,可以确定子进程共享了父进程的地址空间和数据。子进程执行完新程序ps后退出了,然后父进程执行最后退出。

总结

fork和vfork各有其特点,为了节省空间和资源,可以考虑使用vfork。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux的fork和vfork 的相关文章

随机推荐

  • 如何准备大学生电子设计竞赛

    大学生电子设计竞赛难度中上 xff0c 一般有好几个类型题目可以选择 xff0c 参赛者可以根据自己团队的能力 优势去选择合适自己的题目 xff0c 灵活自主空间较大 参赛的同学们可以在暑假好好学习相关内容 xff0c 把往年的题目拿来练练
  • 聊聊ChatGPT

    ChatGPT 这几周科技圈最火的当属ChatGPT xff0c 自媒体中十篇有九篇都是关于ChatGPT的 ChatGPT上可知天文 xff0c 下可知地理 xff0c 还可写论文 搞代 写小说 xff0c 可谓 全能型选手 自从去年11
  • 修改简历有用吗

    看情况 xff0c 一般都是很有用哒 xff01 简历修改会突出你的重点和优点 xff0c 优化你的简历内容 xff0c 让面试官一眼看到简历就被吸引了 xff01 如以上图片所示
  • 运行Python时出现SyntaxError: EOL while scanning string literal解决方法

    当运行Python时 xff0c 出行SyntaxError EOL while scanning string literal 一般是语法出现错误 xff0c 看一下是不是哪里忘记添加符号或是分号 xff1a 这些没打
  • 数据结构选择练习题(有解析)

    前言 已经到期末了 xff0c 昨天进行了一次马原考试 xff0c 那时候挺紧张的 xff0c 那时候虽然写完了试卷 xff0c 但是有4道题是乱写的 xff0c 因为我刚好没有背 xff0c 希望不会挂科吧 然后今天呢 xff0c 就开始
  • 论文阅读_异常检测综述

    英文题目 xff1a Anomaly Detection A Survey 中文题目 xff1a 异常检测综述 论文地址 xff1a https readpaper com paper 2122646361 领域 xff1a 异常检测 发表
  • 解决Mybatis-Plus分页插件无效

    1 导入依赖 span class token tag span class token tag span class token punctuation lt span dependencies span span class token
  • 一、FreeRTOS任务调度相关函数详解

    文章目录 1 FreeRTOS任务调度及相关函数分析1 1 任务创建过程分析1 1 1 任务创建函数分析1 1 2 任务初始化函数分析1 1 3 任务堆栈初始化分析1 1 4 添加任务到就绪列表 1 2 任务删除过程分析1 3 任务挂起过程
  • linux的exit和_exit

    进程退出 退出一个进程有多种方式 xff1a 正常退出 xff1a 在main函数里return 在进程里面调用exit exit 在进程的最后一个子线程调用pthread exit 异常退出 xff1a 被信号 xff08 9 15 xf
  • 三、任务切换之PendSV异常

    文章目录 PendSV异常1 没有PendSV异常的任务切换2 有PendSV异常的任务切换2 1 系统调用引起的任务切换2 2 systick中断引起任务切换2 3 PendSV异常处理函数2 4 寻找下一个要运行的任务2 5 时间片调度
  • Cortex-M系列中断和异常(一)

    文章目录 1 中断与异常1 1 异常的类型1 2 异常及中断的管理1 2 1 中断的一般使用方法 1 3 优先级的定义1 4 向量表和向量表的重定义1 4 1 向量表重定向的应用场景 1 5 中断输入和挂起行为1 5 1 中断请求的类型 1
  • Cortex-M系列中断和异常(三)

    文章目录 Cortex M系列中断和异常1 1 SCB中的寄存器1 1 1 中断控制和状态寄存器 xff08 SCB gt ICSR xff09 1 1 2 向量表偏移寄存器 xff08 SCB gt VTOR xff09 1 1 3 应用
  • Cortex-M系列中断和异常(四)

    文章目录 1 中断及异常的注意事项1 1 中断及异常的优先级配置1 2 中断与栈空间的关系1 3 向量表重定向情况1 4 软件中断1 5 ARM架构及中断 2 函数调用与异常处理的过程2 1 函数调用过程2 2 异常处理过程2 2 1 栈帧
  • Cortex-M芯片低功耗开发

    文章目录 芯片的低功耗1 1 低功耗的测量数据1 2 低功耗的系统特性1 3 低功耗的系统需求1 3 1 Cortex M3和Cortex M4处理器的低功耗特点 1 4 低功耗系统特性1 4 1 休眠模式1 4 2 系统控制寄存器 xff
  • Keil 启动文件详解

    文章目录 1 启动文件详解1 1 启动文件的主要任务1 2 启动文件中的汇编指令1 3 启动代码讲解1 3 1 栈的初始化1 3 2 堆的初始化1 3 3 向量表初始化1 3 4 复位程序1 3 5 中断服务程序1 3 6 用户堆栈初始化
  • TiveC微控制器基础练习1.1源码

    基础练习1 1 软件延时实现LED闪烁 硬件描述 LED2 蓝色 PF0 LED3 绿色 PA4 LED4 红色 PD6 使用这个引脚 注意事项 引脚PF0和PD7比较特殊 默认是保护的 要重新编程操作的话 需要先解锁 小技巧 通过SysC
  • git-lfs filter-process: git-lfs: command not found

    最初是认为网络不稳定 xff0c 或者git版本过低 开始自己的git版本是1 20 xff0c 后续升级为1 32仍旧存在这个问题 之后安装了git lfs xff0c 问题解决 不知道为什么其他同事没有出现该问题 brew instal
  • gazebo和rviz有具体的区别吗?哪个更好用?

    文章来源 xff1a 企鹅号 古月居 https www zhihu com question 268658280 answer 340190866 简单来讲 xff0c 两者的主要功能不同 xff0c 没办法比较哪个更好用 xff0c 如
  • Ubuntu下好用的录屏和视频格式转换工具

    xff08 1 xff09 Ubuntu录屏工具 kazam 安装 sudo apt get install kazam 安装完之后 xff0c 命令行中输入 xff1a kazam 就可以启动工具了 xff0c 可以看到工具界面如下 xf
  • linux的fork和vfork

    fork和vfork 区别 fork函数和vfork函数都可以用来创建一个子进程 他们有什么区别呢 xff1f 首先是fork xff1a 内核会给子进程分配虚拟内存空间和id xff0c 但不会分配物理内存子进程一开始是共享父进程的物理空