Linux-fork(),vfork()和clone的区别

2023-11-11

  在linux系统中,fork(),vfork()和clone函数都可以创建一个进程,但是它们的区别是什么呢???本文就这三者做一个较深入的分析!!!

1.fork()

  fork()函数的作用是创建一个新进程,由fork创建的进程称为子进程,fork函数调用一次返回两次,子进程返回值为0,父进程返回子进程的进程ID。我们知道,一个进程的地

址空间主要由代码段,数据段,堆和栈构成,那么p2就要复制相关的段到物理内存。原始的unix系统的实现的是一种傻

瓜式的进程创建,这些复制包括:

(1)  为子进程的页表分配页面,确定页表的位置;

(2)为子进程的页分配页面,确定子进程页面的位置;

(3)初始化子进程的页表;

(4)把父进程的页复制到子进程对应的页中

从图中我们可以看出除了正文段外,子进程的所有其它段都分配了物理空间,并将父进程的相关内容拷贝过来。父进程的task_struct结构中的打开文件描述符,进程组ID,

回话ID都进行复制。

下面通过简单的代码检测一下fork()函数:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
#include <iostream>
using namespace std;

int main() {
        int num = 1;
        int child;
        if(!(child =fork())) {
		cout<<&num<<endl;
                printf("son process, num: %d, address:%p, pid is: %d\n", num,&num, getpid());
		num++;
		cout<<"num:"<<num<<endl;
		cout<<"address: "<<&num<<endl;
		sleep(60);
		exit(0);
        } else {
		sleep(1);
                printf("father process, num: %d, address:%p, pid is: %d\n", num,&num, getpid());		
		sleep(59);		
		exit(0);
        }
}

进程的虚拟空间:

子进程的虚拟地址空间:


父进程的虚拟地址空间:

可以看到子进程和父进程的地址空间是一样的。

  但是这种方法的效果非常不好,如果在fork子进程之后,立即调用了exec函数簇,那么原先拷贝的父进程的数据段,栈,堆的相关副本都将变为徒劳。后来人们想到了一种

替代的方式,那就是写时复制(Copy-On-write,COW技术),这种技术允许父进程和子进程共享上面的区域,而且内核将这些段的访问权限变成只读。如果是父进程或是子进程中

的任何一个试图修改这些区域,则内核只为修改区域的那块内存制作一个副本,通常是虚拟存储系统的某一个"页".下面是这种技术在没有写操作的时候的的详细图解,如果子进

程或父进程的任何一个有写操作的话,那么被写的那一页才需要复制到物理空间;


从图中可以看到,COW技术在进程调用fork()的时候,并没给子进程的相关段分配内存空间。这种做法在fork()之后调用exec函数簇的过程中效率有很大的提高。这种情况下,内

核只需要为子进程创建一个task_struct,也就是说如果子进程调用exec函数簇执行了另一个可执行文件,那么内核可能只是新建一个task_struct结构体,将父进程的内容拷贝过

,这样就大大节约了盲目拷贝的消耗。

2.vfork()

    vfork()函数也用于创建一个新进程,而该新进程的目的是exec一个新程序,下面我们开看看简单的测试:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
#include <iostream>
using namespace std;

int main() {
        int num = 1;
        int child;
        if(!(child =vfork())) {
		cout<<&num<<endl;
                printf("son process, num: %d, address:%p, pid is: %d\n", num,&num, getpid());
		num++;
		cout<<"num:"<<num<<endl;
		cout<<"address: "<<&num<<endl;
		sleep(2);
		exit(0);
        } else {
		sleep(1);
                printf("father process, num: %d, address:%p, pid is: %d\n", num,&num, getpid());		
		sleep(2);		
		exit(0);
        }
}

测试结果:

从测试结果中我们可以看到,在子进程修改了num变量的值后,父进程的num的值也发生改变,说明对于子进程和父进程来说,它们操作的是同一个地方的num值,下面就是vfork的示意图:

可以看出子进程直接共享了父进程的虚拟进程空间。

3.clone()

  clone()函数是linux系统中,用来创建轻量级进程。

函数原形:

int clone(int (*fn)(void *), void *child_stack, int flags, void *arg);
下面是flags可以取的值
标志                    含义
CLONE_PARENT   创建的子进程的父进程是调用者的父进程,新进程与创建它的进程成了“兄弟”而不是“父子”
CLONE_FS           子进程与父进程共享相同的文件系统,包括root、当前目录、umask
CLONE_FILES      子进程与父进程共享相同的文件描述符(file descriptor)表
CLONE_NEWNS   在新的namespace启动子进程,namespace描述了进程的文件hierarchy
CLONE_SIGHAND   子进程与父进程共享相同的信号处理(signal handler)表
CLONE_PTRACE   若父进程被trace,子进程也被trace
CLONE_VFORK     父进程被挂起,直至子进程释放虚拟内存资源
CLONE_VM           子进程与父进程运行于相同的内存空间
CLONE_PID          子进程在创建时PID与父进程一致
CLONE_THREAD    Linux 2.4中增加以支持POSIX线程标准,子进程与父进程共享相同的线程群
下面的例子是创建一个线程(子进程共享了父进程虚存空间,没有自己独立的虚存空间不能称其为进程)。父进程被挂起当子线程释放虚
存资源后再继续执行。
测试代码1:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
#include <iostream>
using namespace std;
#define FIBER_STACK 8192

int a;
void * stack;
int func(void *){
	cout<<&a<<endl;
        printf("This is son, the pid is:%d, the a is: %d\n", getpid(), ++a);
        free(stack); 
        exit(1);
}
int main(){
        void * stack;
        a = 1;
        stack = malloc(FIBER_STACK);
        if(!stack) {
                printf("The stack failed\n");
                exit(0);
        }
	cout<<&a<<endl;
        printf("creating son thread!!!\n");
        clone(func, (char *)stack + FIBER_STACK,CLONE_VFORK|CLONE_VM, 0);
        printf("This is father, my pid is: %d, the a is: %d\n", getpid(), a);
        exit(1);
}

结果:

测试代码2(做如下修改):

clone(func, (char *)stack + FIBER_STACK,CLONE_VFORK, 0);
结果:

很明显,在测试2中将CLONE_VM删掉之后,子进程和父进程就不会公用页表,子进程创建新的页表。从某种意义上来说,clone其实是fork和vfrok的更高层次版本,,它们的关

系如下(《深入理解linux内核》中描述):

   传统的fork()系统调用在Linux中是用clone()实现的,其中clone()的flags参数指定为sigchld信号以及所有清0的clone标志,而它的child_stack参数是父进程当前的堆栈

指针,因此,父进程和子进程暂时共享一个用户态堆栈。而vfork函数系统调用也是用clone实现的,其中clone()的参数flags指定为sigchld和CLONE_VFORK和CLONE_VM标

志,clone()的参数child_stack等于父进程当前的栈指针!!!

。只是有一点不明白,把int a和void * stack挪到main函数里面之后,就会出现编译错误,显示未定义a和stack,这点有些不懂,望高人指点!!!!



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

Linux-fork(),vfork()和clone的区别 的相关文章

  • 【Linux】调试器---gdb的使用

    文章目录 一 背景知识 二 安装gdb 三 gdb的用法 使用须知 gdb的常用指令 1 进入调试 2 退出调试操作 3 显示源代码 4 设置断点breakPoint 5 查看断点信息 禁用断点 开启断点 删除断点 6 运行程序 开始调试r
  • Linux操作系统之进程命令和库文件

    文章目录 一 有关进程命令 1 ps命令 显示当前终端信息 2 ps ef命令 查看当前终端进程的详细信息 二 前台程序和后台程序模式的切换 1 首先了解前台后台命令 2 前后台的切换 1 kill 命令 2 进程前后台切换 三 runle
  • Linux操作系统之基础命令

    文章目录 一 初识LInux操作系统 Linux操作系统和Windows操作系统的区别 Linux 分为内核版本和发行版本 目录结构命令 二 常用命令 1 ls命令 查看路径下所存在的文件 2 cd命令 切换路径 3 clear 清屏命令
  • fwrite函数的用法

    fwrite函数就是写文件的函数 它的函数原型如下 fwrite const void buffer size t size size t count FILE stream 可以看到这个函数的参数有四个 buffer 数据存储的地址 si
  • Base64系列第四篇 C/C++中使用Base64编码解码(从chromium库中抽取)

    本系列一共四篇 1 Base64系列第一篇 Base64介绍 2 Base64系列第二篇 python中使用Base64编码解码 3 Base64系列第三篇 C C 中使用Base64编码解码 使用boost库 4 Base64系列第四篇
  • 操作系统课程实践5_进程通信

    一 实验目的 1 初步了解Linux环境下进程创建和进程间通信的机制 2 掌握如何利用消息和共享内存进行通信的原理 3 利用POSIX API函数编写实例程序 4 实现父子进程间通过消息传递和共享内存方式进行通信 二 实验内容 编制两个程序
  • NFS高可用方案:NFS+keepalived+Sersync

    1 背景 因为某系统需要部署生产 但是云平台的nas存储资源不足需要重新采购 采购周期较长 需要有一个临时的解决方案 这样时候就需要采用nfs服务来提供网络存储服务了 在部署nfs服务的时候需要考虑生产环境需要有一定的高可用性 经过考虑之后
  • linux文件时间戳(atime, mtime, ctime)

    简介 在linux系统创建一个文件后 使用stat lt 文件名 gt 命令行查看文件状态 总是能看到 3 个时间戳 如下图所示 从上图可以看到 touch命令创建文件abc后 使用 stat abc命令行查看abc文件的状态 显示了3个时
  • arm ldr/ld/数据加载系列指令和adr指令

    ldrb指令 1 语法 armv7手册语法 LDRB
  • 查看Linux下rpm文件安装到哪个路径

    命令 root localhost rpm qpl xxx rpm more
  • 【Linux】Ubuntu20.04版本安装谷歌中文输入法【教程】

    Linux Ubuntu20 04版本安装谷歌中文输入法 教程 文章目录 Linux Ubuntu20 04版本安装谷歌中文输入法 教程 一 下载fcitx googlepinyin 二 配置Language Support Referen
  • Docker学习笔记

    五 Docker 1 简介 Docker是一个开源的应用容器引擎 是一个轻量级容器技术 Docker支持将软件编译成一个镜像 然后在镜像中各种软件做好配置 将镜像发布出去 其他使用者可以直接使用这个镜像 运行中的这个镜像称为容器 容器启动是
  • Linux的进程管理

    目录 1 概述 2 进程描述符 2 1 进程描述符的分配 2 2 进程描述符的存放 2 3 进程状态 2 4 进程上下文 2 5 进程家族树 3 进程的创建 4 进程的终结 5 线程的实现 1 概述 进程是执行期的代码 但是进程不止包括这样
  • Linux 多线程 ( 多线程概念 )

    文章目录 Linux线程概念 什么是线程 二级页表 线程的优点 线程的缺点 线程异常 Linux线程概念 什么是线程 在一个程序里的一个执行路线叫做线程 thread 更准确的定义为 线程是一个进程内部的控制序列 一切进程至少有一个执行线程
  • 多线程的同步与互斥——读者写者模型

    在读者写者模型中 同样有 一二三 一个交易场所 两种角色 三种关系 在读者写着模型中 读者与读者之间是共享的关系 因为并没有改变资源 所以不需要互斥 写者与写者之间是互斥的关系 读者与写者之间是同步与互斥的关系 那么如何实现这么复杂的关系呢
  • 进程概念

    基本概念 进程是程序的一个执行实例 从内核来看 进程是担当分配系统资源的实体 注 在Linux操作系统中 大多数指令都是创建了一个个的进程 操做系统如何管理内存 答 使用一个结构体 PCB 来描述进程 使用高效的数据结构来组织进程 描述进程
  • Linux Shell程序设计(2)

    实验十一 Shell程序设计 2 一 实验要求 综合运用shell编程知识进行设计性编程 二 实验内容和实验步骤 1 实验内容 假设你作为某工厂生产管理员 需要负责统计各车间每天生产的产品数据 你的计算机安装了双硬盘 为了保证数据安全 你在
  • 什么是软连接,以及软连接在linux系统中的用法

    软连接是linux中一个常用命令 它的功能是为某一个文件在另外一个位置建立一个同步的链接 软连接类似与c语言中的指针 传递的是文件的地址 更形象一些 软连接类似于WINDOWS系统中的快捷方式 例如 在a文件夹下存在一个文件hello 如果
  • ext4 buddy块分配算法源码剖析

    概述 ext4 buddy块分配算法的函数是ext4 mb regular allocator 阅读本文之前需要先看下ext4 mballoc之buddy算法 nginux的博客 CSDN博客 ext4 mb regular allocat
  • 5、Ubuntu20常用操作_进程管理&重定向和管道&常用命令&网络管理&构建web静态服务器nginx

    进程管理 进程的概念 大家比较熟悉 Windows 下的可执行文件 就是那些扩展名为exe的文件 大家知道 只需要鼠标双击这些程序 就可以运行了 程序运行起来后 我们把这个程序正在运行的 实例 称之为 进程 操作系统对每个进程都分配一个数字

随机推荐

  • 51 openEuler搭建PostgreSQL数据库服务器-安装、运行和卸载

    文章目录 51 openEuler搭建PostgreSQL数据库服务器 安装 运行和卸载 51 1 安装 51 2 运行 51 2 1 初始化数据库 51 2 2 启动数据库 51 2 3 登录数据库 51 2 4 配置数据库账号密码 51
  • js实现雪花飘落效果

    js实现雪花飘落效果 我们可以先看看效果 点这里 雪花 其实总的代码都不到 100 行 代码很少 因此 css 样式 和 js 代码我都放在一个 HTML 文件里面了 我们先看看主体的 HTML 代码 div div html 的代码就只有
  • 搭建目标检测模型之Domain Adaptive Faster R-CNN for Object Detection in the Wild

    搭建环境 方法1 直接搭建环境 报错及解决方法 准备数据集 官方数据集 训练模型 测试模型 训练结果 有问题 搭建环境 方法1 直接搭建环境 克隆项目Domain Adaptive Faster RCNN PyTorch git clone
  • 华为od机试题8 真题

    华为od机试题 真题 10 输出最多类型的个数 11 树根节点到最小的叶子节点的路径 12 货车最大载货量 13 太阳能板最大面积 14 单词接龙 17 输出连续出现次数第k多的字母的次数 18 喊7 19 删除出现次数最少的字符 以下题目
  • actuator--基础--08--application.yml配置

    actuator 基础 08 application yml配置 management endpoints 暴露 EndPoint 以供访问 有jmx和web两种方式 exclude 的优先级高于 include jmx exposure
  • windows7 64位机上,libjpeg-turbo的安装和使用

    libjpeg turbo是对libjpeg的扩展 支持SIMD指令 如X86架构的MMX SSE SSE2 3DNOW ARM架构的NEON 在对jpeg进行编码和解码的过程中能提高速度 MMX 多媒体扩展的缩写 第六代CPU芯片重要特点
  • 【Modbus】 RTU CRC校验码计算方法

    Modbus是美国Modicon公司 即现在的Schneider Electric公司 于1979年开发的一种通信协议 其目的是采用一根双绞线实现多个设备之间的通信 Modbus 协议采用问答式的通信方式 具有简单 硬件便宜 通用性强 使用
  • 2023_华为OD机试真题_Java_001_AI处理器组合

    AI处理器组合 题目描述 某公司研发了一款高性能AI处理器 每台物理设备具备8颗AI处理器 编号分别为0 1 2 3 4 5 6 7 编号0 3的处理器处于同一个链路中 编号4 7的处理器处于另外一个链路中 不通链路中的处理器不能通信 如下
  • pip 删除安装包_最新版pip用法一览

    pip 是 Python 包管理工具 该工具提供了对Python 包的查找 下载 安装 卸载的功能 熟练使用此工具 也是python的基本功 https pypi org目前最新版本为20 2 2 以下就以此版本来演示其使用 下面演示 是在
  • pytorch学习(六)---搭建简单的神经网络以及sequential的使用

    本篇自学笔记来自于b站 PyTorch深度学习快速入门教程 绝对通俗易懂 小土堆 Up主讲的非常通俗易懂 文章下方有视频连接 如有需要可移步up主讲解视频 如有侵权 实非故意 深表歉意 请与我联系 删除相关内容 本节以CIFAR10的模型结
  • emwin多语言实现的两种方式

    MCU开发中经常会涉及到多语言的制作和支持 本文将介绍两种制作字库的方法 字库的实现主要包含两部分 一是 字库 一是要显示的字符串 将这两个东西准备好 就可以实现了 第一种方法 详细的可以直接参考这篇博客 可 EMWIN 多国语言实现方法
  • 【信号采集】基于FPGA的高速信号采集系统

    1 高速采集系统实现的功能 FPGA内部功能模块组成 2 高速ADC接口的FPGA实现 3 数字下变频 DDC 的FPGA实现 4 三倍抽取功能的FPGA实现 5 Aurora接口的FPGA实现 高速采集系统的功能和组成 1 实现功能 对中
  • 《消息队列高手课》传输协议:应用程序之间对话的语言

    传输协议就是应用程序之间对话的语言 设计传输协议 并没有太多规范和要求 只要是通信双方的应用程序都能正确处理这个协议 并且没有歧义就好了 这节课 我们就来说一下设计高性能传输协议的一些方法和技巧 如何 断句 既然传输协议也是一种语言 那么在
  • CentOS8基础篇5:用户账号与用户组的创建

    一 用户与用户组概念 Linux是一个多用户 多任务的服务器操作系统 多用户多任务指可以在系统上建立多个用户 而多个用户可以在同一时间内登录同一个系统执行各自不同的任务 而互不影响 Linux用户是根据角色定义的 具体分为三种角色 超级用户
  • C++中拒绝编译器自动生成copy构造函数和copy赋值运算符操作(6)---《Effective C++》

    C 是一片荆棘遍布的雷区 等待用于挑战的你去探索 在 Effective C 系列的第5篇中我们已经看到当用户进行赋值或者拷贝操作的时候 即使我们没有定义拷贝构造函数或者拷贝赋值运算符操作 编译器也会自动为其生成copy构造函数和copy赋
  • P50发布,鸿蒙OS用户突破4000万!

    大家期盼已久的华为 P50 系列手机终于来了 7 月 29 日晚间 华为在线上举行 万象新生 为主题的旗舰新品发布会 华为旗舰新机 P50 系列正式全球发布 太难了 迟到 4 个月的 P50 发布 在今年 6 月份华为鸿蒙 2 0 发布会上
  • 基于HashHeap的LFU实现

    普通heap支持的操作和queue stack一样 就是push pop 只是pop出的是最小值 具体点就是add delMin hashheap支持一般HashMap的功能 同时维护最小值 和LinkedHashMap是对等的 后者是Ha
  • 手机开启应急预警通知 / 地震预警

    前言 安卓手机在检测到地震时 将发送地震预警通知 但此设置是默认关闭的 原因是以防引发用户恐慌从而引发安全问题 且开启此设置需要完成指引教程 因此默认关闭此设置 下文介绍如何开启此设置 开启方法 华为手机开启方法 以华为手机为例 详细介绍开
  • Metasploit渗透测试框架的基本使用

    1 Metasploit体系框架 1 基础库 metasploit基础库文件位于源码根目录路径下的libraries目录中 包括Rex framework core和framework base三部分 Rex是整个框架所依赖的最基础的一些组
  • Linux-fork(),vfork()和clone的区别

    在linux系统中 fork vfork 和clone函数都可以创建一个进程 但是它们的区别是什么呢 本文就这三者做一个较深入的分析 1 fork fork 函数的作用是创建一个新进程 由fork创建的进程称为子进程 fork函数调用一次返