fork函数详解【Linux】

fork函数详解【Linux】

  • fork函数的概念
  • fork调用后的底层细节
  • 解释fork学习中的一些笔记和问题
  • fork的写实拷贝
    • 深拷贝的策略
  • fork调用失败的原因

fork函数的概念

  调用fork函数可以在已存在的进程中创建一个子进程,此时,新进程叫做子进程,原进程叫做父进程。

  #include <unistd.h>
  pid_t fork(void);
 其中pid_t的底层是int;
在这里插入图片描述
返回值::子进程中返回0,父进程返回子进程id,出错返回-1
也就是这样:

#include <iostream>
#include <unistd.h>
int main()
{
    pid_t fd = fork();
    if (fd == 0)
    {
        //this area is child

    }
    else if(fd > 0)
    {
        // this area is parent

    }
    else
    {
        // this area is error

    }

    return 0;
}

fork调用后的底层细节

  当我们在用户空间调用了fork以后,控制会从用户空间转移到内核空间,因为fork属于系统调用,然后内核会:

  1. 为子进程分配新的内存块和内核数据结构。
  2. 以父进程为模板,将父进程的pcb和虚拟内存地址以及页表汇中的内容完整复制一份给子进程,以至于虚拟内存地址和页表以及页表和物理地址空间的映射关系,父子进程此时都是一模一样的。
  3. 将子进程的pcb添加到系统进程列表中。
  4. fork返回,开始进程调度器调度。

解释fork学习中的一些笔记和问题

  1. 同一个程序,每次启动运行时,分配的pid都可能不同。
  2. 命令行中的父进程一般是命令行解释器bash,命令行中启动的进程,都是bash的子进程。
  3. Linux中创建子进程有两种方式:
    3.1. 在命令行行中直接启动进程。(启动进程的本质就是创建进程吗)
    3.2. 通过代码来创建子进程。(一般是由父进程创建)
  4. 只有父进程执行fork之前的代码,fork之后的代码父子进程都要执行。
  5. 创建子进程的原因:想让子进程协助父进程完成一些工作,这些工作是单进程完成不了的。(比如边下载边播放视频),创建子进程是为了和父进程做不一样的事。
  6. 为什么fork的两个返回值会给父进程返回子进程pid,给子进程返回0?
    :答:因为父子进程的数量比例是 1:n , 为了使得父子进程能够一一对应,具有唯一性,且子进程主要是为了协助父进程,父进程得到了子进程的pid能够确定唯一的子进程,方便调用子进程。
  7. fork之后,父子进程谁先运行?
    : 答:这个跟内核的调度机制有关,哪一个进程的pcb先被选择调度,哪一个进程就先执行,所以是不确定的。由各自pcb中的调度信息(时间片,优先级)和调度器算法决定,也就是有OS决定。

fork的写实拷贝

  由于虚拟内存地址和页表以及页表和物理地址空间的映射关系,父子进程此时都是一模一样的。所以可以说父子继承一开始都是使用同一块地址空间。

#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
    int a = 8;
    pid_t fd = fork();
    if (fd == 0)
    {
        a = 3;
        std::cout << "child: " << a << std::endl;
    }
    if (fd > 0)
    {
        std::cout << "parent: " << a << std::endl;
    }

    wait(NULL);
    return 0;
}

在这里插入图片描述
  看完上面这份代码,为什么明明父子进程的a是同一块地址空间的,按理来说子进程修改了a为3,父进程的a为什么还是8呢?难道是结论错误了吗?

#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
    int a = 8;
    std::cout << &a << std::endl;
    pid_t fd = fork();
    if (fd == 0)
    {
        a = 3;
        std::cout << "child: " << &a << std::endl;
    }
    if (fd > 0)
    {
        std::cout << "parent: " << &a << std::endl;
    }

    wait(NULL);
    return 0;
}

在这里插入图片描述
  通过上面这个代码也可以清楚知道父子进程的a指向的地址空间确实是同一个。

  这里的原因是因为我们所看到的地址叫做虚拟内存空间,每一个进程都会有一份虚拟内存和一个页表。但是物理内存只有一个,页表中保存着虚拟内存和物理内存之间的一份映射关系。

  我们可以浅显的将页表看做下图(真正页表中的字段不止三个,但是此刻这三个字段足以说明问题);
在这里插入图片描述
  所以真实情况是:子进程的创建确实以父进程为模板将其内容拷贝到了子进程的内核数据结构中,但是当数据有所变化时,就以深拷贝的方式父子进程各自私有一份。

深拷贝的策略

  1. 父进程创建子进程的时候会先将自己页表中的访问权限字段中的读写权限改为只读,然后再创建,使得父子进程的数据都是只读。
  2. 当父子进程任意一方试图更改共同数据,就会触发页表权限问题,在页表映射转换时出现权限问题会有两种情况:
    • 真的出错了
    • 不是出错,触发深拷贝的策略机制,需要进程重新申请内存
      此时显然是属于后者。
  3. 此时再物理内存中开辟了一段新空间,然后将更改后的数据写入到内存,页表中的物理地址也要改成新物理空间的地址。
  4. 因为没有更改虚拟地址,所以我们打印出来的地址会发现深拷贝之后的虚拟地址依旧没有改变。这也就解释了开头那份代码所带来的问题。

在这里插入图片描述

fork调用失败的原因

  • 系统中有太多的进程
  • 实际用户的进程数超过了限制

    😄 创作不易,你的点赞和关注都是对我莫大的鼓励,再次感谢您的观看😄

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/275091.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

k8s二进制部署--部署高可用

连接上文 notready是因为没有网络&#xff0c;因此无法创建pod k8s的CNI网络插件模式 1.pod内部&#xff0c;容器与容器之间的通信。 在同一个pod中的容器共享资源和网络&#xff0c;使用同一个网络命名空间。 2.同一个node节点之内&#xff0c;不同pod之间的通信。 每个pod都…

element ui Checkbox 多选框组件 lable不支持Object类型的值的问题

浅浅记录一下&#xff0c;遇到这个问题的心理路程吧&#xff0c;首先我遇到的问题是多选框的值回显不打对勾&#xff0c;&#xff08;例如&#xff1a;你新增的时候多选&#xff0c;然后点击编辑的时候选过的值没有被勾选&#xff0c;其实是被勾选上了&#xff0c;但是没有显示…

Linux操作系统——进程(六) 进程地址空间

进程地址空间 C/C程序员一般将我们所写的程序看成如下这种结构&#xff1a; 我们所写的程序通过编译编译之后就可以以这样的方式进行分布. 我们先通过编写一段C语言代码来进行验证&#xff1a; 运行结果&#xff1a; 我们可以看出来上述地址遵循的就是我们上面画的一种结构。…

【附视频解析】Jmeter接口之间关联调用(获取上一个接口的返回值作为下一个接口的请求参数)

正则表达式&#xff1a; 具体如何操作&#xff1a; 1. 草稿保存&#xff0c; 此请求的响应数据的id 为发布总结的请求参数draft_id 2. 草稿保存的响应数据 3.在草稿保存的请求中&#xff0c;添加后置处理器- 正则表达式提取器&#xff0c; 提取响应数据的id信息 4. 发布总结请…

Java 缓存中间件

Java 缓存中间件 关键词&#xff1a;Spring Cache、J2Cache、JetCache 一 、JSR 107 JSR107 中制订了 Java 缓存的规范。 因此&#xff0c;在很多缓存框架、缓存库中&#xff0c;其 API 都参考了 JSR 107 规范。 img Java Caching 定义了 5 个核心接口 CachingProvider - 定义…

私有部署ELK,搭建自己的日志中心(三)-- Logstash的安装与使用

一、部署ELK 上文把采集端filebeat如何使用介绍完&#xff0c;现在随着数据的链路&#xff0c;继续~~ 同样&#xff0c;使用docker-compose部署&#xff1a; version: "3" services:elasticsearch:container_name: elasticsearchimage: elastic/elasticsearch:7.9…

Kafka学习笔记1(千峰教育)

Kafka学习笔记1&#xff08;千峰教育&#xff09; 一、为什么使用消息队列1.使用同步的通信方式来解决多个服务之间的通信2.使用异步的通信方式 二、消息队列的流派1.有broker2.无broker 三、Kafka的基本知识1.Kafk2a的安装2.Kafka中的一些基本概念3.创建topic4.发送消息5.消费…

sonarqube安装踩坑记录

如果用java1.8和mysql&#xff0c;则sonarqube版本不能超过7.8&#xff0c;看这里。 sonarqube7.8安装包地址&#xff1a; https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.8.zip 安装步骤&#xff1a; 1、下载sonarqube安装包 wget https://binari…

【PowerMockito:编写单元测试过程中采用when打桩失效的问题】

问题描述 正如上图所示&#xff0c;采用when打桩了&#xff0c;但是&#xff0c;实际执行的时候还是返回null。 解决方案 打桩时直接用any() 但是这样可能出现一个mybatisplus的异常&#xff0c;所以在测试类中需要加入以下代码片段&#xff1a; Beforepublic void setUp() …

软件测试/测试开发丨Pytest 参数化用例

参数化 通过参数的方式传递数据&#xff0c;从而实现数据和脚本分离。并且可以实现用例的重复生成与执行。 参数化应用场景 测试登录场景 测试登录成功&#xff0c;登录失败(账号错误&#xff0c;密码错误)创建多种账号: 中⽂文账号&#xff0c;英⽂文账号 普通测试用例方法 …

nginx 1.14.0引入自己使用C语言写的模块

参考的一篇博客《为NGINX编译第三方动态模块》 源码的地址&#xff1a;https://github.com/perusio/nginx-hello-world-module/tree/master。 源码被我放到系统中/root/nginx-hello-world-module目录下&#xff0c;ls /root/nginx-hello-world-module可以看一下源码里边的内容。…

C++初阶(十七)模板进阶

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、非类型模板参数二、模板的特化1、概念2、函数模板特化3、类模板特化1、全特化2、偏特化 三…

【tcp】TCP CLOSE_WAIT问题分析与定位

一、问题背景 某日&#xff0c;运维突然在群里突然丢出告警信息&#xff1a; 对象类型&#xff1a;主机 检测规则&#xff1a;NET.TCP.CLOSE.WAIT 告警内容&#xff1a;CLOSE_WAIT状态的TCP连接数大于500 ....image.png 上面告警信息已经说的很明白&#xff0c;CLOSE_WAIT状…

Ruff物联网数采网关助力工业企业数字化转型,降本增效

如今&#xff0c;随着工厂数字化转型进程的加速&#xff0c;越来越多的企业对于设备数据感知层及传输层的应用越来越重视&#xff0c;因此工业数采网关也走进了很多人的视野&#xff0c;在工厂数字化转型中扮演着关键角色。 物联网数据采集网关能将各种传感器、执行器等设备连…

主浏览器优化之路1——你现在在用的是什么浏览器?Edge?谷歌?火狐?360!?

上一世&#xff0c;我的浏览器之路 引言为什么要用两个浏览器为什么一定要放弃火狐结尾给大家一个猜数字小游戏&#xff08;测运气&#xff09; 引言 小时候&#xff0c;我一开始上网的浏览器是2345王牌浏览器吧&#xff0c; 因为上面集成了很多网站&#xff0c;我记得上面有7…

五轴机床测头:高精度曲面检测的得力工具

五轴机床测头广泛应用于制造业中的高精度加工领域。它能够准确、快速地检测出曲面的形状、尺寸和特征&#xff0c;为生产过程中的质量控制提供了重要支持。 五轴机床测头是一款具有3维5向探测功能的红外触发机床测头&#xff0c;广泛应用于 3 轴、5 轴加工中心&#xff0c;以及…

【Bootstrap学习 day1】

Bootstrap5 网格的基本结构 等宽响应式列 Bootstrap 5 网格系统有6个类&#xff1a; .col-针对所有设备 col-sm平板-屏幕宽度等于或大于576px。 .col-md-桌面显示器&#xff0c;屏幕宽度等于或大于768px col-lg大桌面显示器&#xff0c;屏幕宽度等于或大于992px col-xl特大桌面…

百度CTO王海峰:文心一言用户规模破1亿

▶ 写在前面▶ 飞桨开发者已达1070万▶ 文心一言用户规模破亿&#xff0c;日提问量快速增长 ▶ 写在前面 “文心一言用户规模突破 1 亿。”12 月 28日&#xff0c;百度首席技术官、深度学习技术及应用国家工程研究中心主任王海峰在第十届 WAVE SUMMIT 深度学习开发者大会上宣布…

事务的简介

一、什么是事务 事务是一组数据库的操作序列&#xff0c;包含一个或多个sql操作命令&#xff08;增删改&#xff09;&#xff0c;事务将所有的操作命令看做一个不可分割的整体&#xff0c;向数据库系统提交或撤销操作&#xff0c;所有操作要么执行要么不执行。 ●事务是一种机…

大创项目推荐 深度学习YOLO安检管制物品识别与检测 - python opencv

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络4 Yolov55 模型训练6 实现效果7 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习YOLO安检管制误判识别与检测 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&…