Linux|fork命令及其使用的写时拷贝技术
fork复制进程
fork通过以下步骤来复制进程:
- 分配新的进程控制块:内核为新进程分配一个新的进程控制块(PCB),用于存储进程的相关信息,如进程 ID、状态、寄存器值、内存指针等。
- 复制进程地址空间:将父进程的地址空间(包括代码段、数据段、堆和栈等)复制到新进程的地址空间中。这意味着新进程将拥有与父进程相同的程序代码和数据。
- 复制文件描述符表:父进程打开的文件描述符在子进程中也会被复制,使得子进程可以访问相同的文件资源。
- 设置进程状态和 ID:新进程被设置为就绪状态,等待被调度执行。同时,内核为子进程分配一个唯一的进程 ID。
- 返回控制:fork系统调用在父进程和子进程中都返回。在父进程中,返回值是子进程的进程 ID;在子进程中,返回值是 0。通过检查返回值,父进程和子进程可以区分彼此,并执行不同的代码路径。
简单来说:fork是把已有的进程复制一份,把对应父进程的PCB也复制了一份,然后申请一个PID,子进程,子进程的PID=父进程的PID+1;
通过这些步骤,fork
创建了一个与父进程几乎完全相同的子进程,子进程可以独立于父进程运行,并可以在适当的时候执行自己的代码逻辑。
在Linux上示例:
创建一个main.c,通过if else返回值来操作父子进程做不一样的事情:
#include <stdio.h>#include <unistd.h>#include <assert.h>#include <stdlib.h>int main(){char *s=NULL;int n=0;//控制父子进程执行的次数;pid_t id=fork();assert(id!=-1);if(id==0)//子进程{s="child";n=3;}else//父进程{s="parent";n=7;}//父子进程int i=0;for(;i<n;i++){printf("s=%s\n",s);sleep(1);}exit(0);}
多运行几次就会发现每次执行结果不完全一定:
要解释这执行结果不同的原因,我们先了解下printf的缓冲区机制
下面介绍一下printf
的缓冲区机制
printf
函数通常会将输出先存储在缓冲区中,而不是立即输出到终端或其他目标设备。这样做的目的是为了提高输出效率,减少系统调用的次数。例如,当多次调用printf
输出少量数据时,这些数据会先在缓冲区中积累,直到缓冲区满或者遇到特定的条件(如换行符\n
),才会将缓冲区中的内容一次性输出。
在Linux上用代码演示一下:
创建一个main.c文件
使用exit(0)命令退出程序
其中,exit是先刷新缓冲区,然后再调用_exit(真正的退出); _exit直接退出,不会刷新缓冲区;
编译后运行,结果是三秒后输出hello(注意这里hello后没有加\n,\n会刷新缓冲区,后面会详细总结)
原因是程序执行printf时先将hello放到缓冲区,不是直接打印到屏幕上,然后执行sleep(3)休眠3秒,然后执行到exit(0)时先刷新缓冲区,此时屏幕上显示hello,随后程序结束运行。
强制刷新 (1)方法一:遇到\n自动刷新 printf("hello\n"); (2)使用fflush刷新屏幕 fflush(stdout);
总结: printf将内容先写入到缓冲区中,缓冲区刷新到界面(屏幕)上的条件是:
(1)缓冲区放满
(2)缓冲区未满,强制刷新缓冲区到屏幕(方法一:\n;方法二:主动刷新:fflush(stdout));
(3)程序结束时,自动刷新缓冲区:exit方法
了解printf缓冲区这一特点后便清楚fork实际的运行结果不确定的原因了:
当使用fork
创建子进程时,子进程会继承父进程的内存空间,包括printf
函数的缓冲区。如果在父进程中printf
了一些内容但缓冲区尚未刷新,那么在fork
之后,子进程中也会有一份相同的未刷新缓冲区内容。这可能导致一些意外的输出结果。例如,如果父进程在fork
之前调用printf
输出了一些字符串但没有换行,然后fork
创建了子进程,接着父进程和子进程都继续执行,那么可能会出现父进程和子进程的输出混合在一起的情况,因为它们共享了原来的缓冲区内容,并且在后续的执行中可能会各自刷新缓冲区。
fork的时机:
fork产生的这个子进程不是从头开始执行的,而是从fork之后开始执行的,就是说子进程直接从fork下面的代码开始执行,具体的是说从得到fork的返回值后子进程开始执行,子进程不会再fork了,所以不会出现子进程再去fork产生一个子进程的问题. 也就是说:fork返回值语句,父进程fork返回子进程的PID,子进程fork返回0,二者分别独立执行各自的程序。
补充系统调用函数:getppid和getpid(头文件<unistd.h>
getppid:得到一个进程的父进程的PID;
getpid:得到当前进程的PID;
我们在原先的代码中增加这两个函数调用:
#include <stdio.h>#include <unistd.h>#include <assert.h>#include <stdlib.h>int main(){char *s=NULL;int n=0;//控制父子进程执行的次数;pid_t id=fork();assert(id!=-1);if(id==0)//子进程{s="child";n=3;}else//父进程{s="parent";n=7;}//父子进程int i=0;for(;i<n;i++){printf("s=%s,pid=%d,ppid=%d\n",s,getpid(),getppid());sleep(1);}exit(0);}
运行结果如下图:
观察发现父进程的父进程pid对应bash的pid,这里的bash是系统命令解释器:
此处拓展介绍一下命令解释器:
在计算机科学中,命令解释器Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(command interpreter,命令解析器)。它类似于DOS下的COMMAND.COM和后来的cmd.exe。它接收用户命令,然后调用相应的应用程序。
我们就是通过命令解释器(称为shell)(bash是命令解释器中的一种)和内核和系统进行交互的(Windows通过图形界面进行交互的);例如我们把ls交给bash,bash帮我们运行ls,然后把结果给用户;
回归正题——fork
fork背后多采用写时拷贝技术
写时拷贝技术
写时拷贝是一种延迟拷贝的策略。在fork
创建子进程时,并不立即复制父进程的所有内存页面,而是让父进程和子进程共享这些页面,并将这些页面标记为只读。只有当父进程或子进程试图对某个共享页面进行写操作时,操作系统才会为该页面分配新的内存空间,并将原页面的内容复制到新的页面中,然后让进行写操作的进程在新的页面上进行修改。
如果不使用写时拷贝技术
第一:复制开销比较大; 第二:占用内存空间;
使用写时拷贝技术:
父子进程逻辑地址一样,但是物理地址是不一样的(多进程逻辑地址相同,对应的物理地址不一定相同)
简单来说就是fork的时候,子进程直接把父进程的页表复制过来,子进程发生写入(修改)的时候才分配内存复制,然后进行相应的页表修改,因此写时拷贝是一种可以推迟甚至免除拷贝数据的技术。
内容来源内核与设计22页:
到此fork及其背后运用的写时拷贝技术就介绍完啦!
如果觉得有用可以点个赞,谢谢支持呀,会持续输出更新知识点,感兴趣可以关注一下!
相关文章:
Linux|fork命令及其使用的写时拷贝技术
fork复制进程 fork通过以下步骤来复制进程: 分配新的进程控制块:内核为新进程分配一个新的进程控制块(PCB),用于存储进程的相关信息,如进程 ID、状态、寄存器值、内存指针等。复制进程地址空间࿱…...
sgpt 终端使用指南
1. 什么是 sgpt? sgpt 是一个基于 OpenAI API 的命令行工具,允许用户在终端中与 AI 进行交互,支持自然语言对话、代码生成、Shell 命令生成等功能。本文将介绍 sgpt 的安装方法、基本用法、配置文件路径及修改方式,并提供完整的配…...
python如何提取html中所有的图片链接
在Python中,你可以使用BeautifulSoup库来解析HTML内容,并提取其中所有的图片链接(即<img>标签的src属性)。以下是一个示例代码,展示了如何做到这一点: 首先,确保你已经安装了BeautifulSo…...
第十一章 | 智能合约主网部署与验证详解
📚 第十一章 | 智能合约主网部署与验证详解 ——让你的合约真正上线、公开、透明! ✅ 本章导读 前面我们写了各种合约,ERC20、NFT、DAO…… 但只在本地测试或测试网上部署运行,项目还没“上链”! 主网上线部署&#…...
一文读懂Python之json模块(33)
一、json模块介绍 json模块的功能是将序列化的json数据从文件里读取出来或者存入文件。json是一种轻量级的数据交换格式,在大部分语言中,它被理解为数组(array)。 json模块序列化与反序列化的过程分别是 encoding和 decoding。e…...
TextView、AppCompatTextView和MaterialTextView该用哪一个?Android UI 组件发展史与演进对照表
在 Android 开发中,UI 组件一直在不断演进,从最初的原生组件,到 Support Library(AppCompat 兼容库),再到如今的 Material Design 组件。这篇文章将梳理 Android UI 组件的发展历史,并提供详细的…...
三层网络 (服务器1 和 服务器2 在不同网段)
服务器1 和 服务器2 在不同网段,并且通过三层交换机实现通信 1. 网络拓扑 假设网络拓扑如下: 服务器1: mac0:IP 地址 192.168.1.10/24,网关 192.168.1.1 mac1:IP 地址 10.0.1.10/24,网关 10.0…...
23种设计模式-创建型模式-工厂方法
文章目录 简介场景问题1. 直接依赖具体实现2. 违反开闭原则3. 条件分支泛滥4. 代码重复风险 解决根本问题完整类图完整代码说明核心优势代码优化静态配置表动态策略 总结 简介 工厂方法是一种创建型设计模式,它提供了在父类中创建对象的接口,但允许子类…...
el-table单元格编辑,动态增删行,回车/上下左右箭头切换单元格
🤵 作者:coderYYY 🧑 个人简介:前端程序媛,目前主攻web前端,后端辅助,其他技术知识也会偶尔分享🍀欢迎和我一起交流!🚀(评论和私信一般会回!!) 👉 个人专栏推荐:《前端项目教程以及代码》 基于 Element UI 实现表格单元格编辑与键盘导航功能 Element UI …...
基于springboot的新闻推荐系统(045)
摘要 随着信息互联网购物的飞速发展,国内放开了自媒体的政策,一般企业都开始开发属于自己内容分发平台的网站。本文介绍了新闻推荐系统的开发全过程。通过分析企业对于新闻推荐系统的需求,创建了一个计算机管理新闻推荐系统的方案。文章介绍了…...
解决Selenium滑动页面到指定元素,点击失效的问题
White graces:个人主页 🙉专栏推荐:Java入门知识🙉 🐹今日诗词:君失臣兮龙为鱼,权归臣兮鼠变虎🐹 ⛳️点赞 ☀️收藏⭐️关注💬卑微小博主🙏 ⛳️点赞 ☀️收藏⭐️关注Ǵ…...
医学图像白血病分割数据集labelme格式245张5类别
数据集格式:labelme格式(不包含mask文件,仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数):245 标注数量(json文件个数):245 标注类别数:5 标注类别名称:["basophil Leukemia","Lymphocyte…...
深度学习Python编程:从入门到工程实践
第一章 Python语言概述与生态体系 1.3 Python在工业界的应用场景 # 示例:使用FastAPI构建RESTful接口 from fastapi import FastAPI from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strprice: float@app.post("/items/") async def cr…...
DHCPv6 Stateless Vs Stateful Vs Stateless Stateful
DHCPv6常见配置模式 在 IPv6 网络中,DHCPv6 的 Stateless(无状态)、Stateful(有状态) 和 Stateless + Stateful(混合模式) 是三种常见的配置模式。它们的主要区别在于客户端如何获取 IPv6 地址和其他网络配置信息(如 DNS 服务器)。 Stateless(无状态)模式 Statele…...
Redis Cluster 详解
Redis Cluster 详解 1. 为什么需要 Redis Cluster? Redis 作为一个高性能的内存数据库,在单机模式下可能会遇到以下问题: 单机容量受限:Redis 是基于内存存储的,单机的内存资源有限,单实例的 Redis 只能…...
Spring(8)——MyBatis入门(2)
一、Mybatis的xml配置文件 Mybatis的开发有两种方式: 注解xml 上一篇博客介绍了用注解的方式操作数据库,这一篇介绍通过xml配置文件的方式操作数据库。 1.1 xml配置文件规则 在Mybatis中使用XML映射文件方式开发,需要符合一定的规范&…...
解析DeepSeek的技术内核:混合专家架构如何重塑AI效能
解析DeepSeek的技术内核:混合专家架构如何重塑AI效能 在当今大型语言模型(LLM)竞争激烈的赛道上,中国AI企业DeepSeek凭借其独特的技术路线脱颖而出。其核心优势之一,便是对混合专家(Mixture of Experts&…...
Android在kts中简单使用AIDL
Android在kts中简单使用AIDL AIDL相信做Android都有所了解,跨进程通信会经常使用,这里就不展开讲解原理跨进程通信的方式了,最近项目换成kts的方式,于是把aidl也换成了统一的方式,其中遇到了很多问题,这里…...
【C++】类和对象(匿名对象)
匿名对象 用 类型(实参) 定义出来的对象叫做匿名对象,相比之前我们定义的 类型 对象名(实参) 定义出来叫有名对象匿名对象生命周期只在当前一行,一般临时定义一个对象当前用一下即可,就可以定义匿名对象。 class A { public:A(int a 0):_a…...
Spring boot 3.4 后 SDK 升级,暨 UI API/MCP 计划
PS 写这篇文章后看到 A Deep Dive Into MCP and the Future of AI Tooling | Andreessen HorowitzWe explore what MCP is, how it changes the way AI interacts with tools, what developers are already building, and the challenges that still need solving. https://a1…...
使用Helm安装、 升级、 回滚Kubernetes应用
前言 在我之前做的项目里,我们对Microk8s微服务的更新是通过自制tar包的方式做的, tar包存储了镜像和YAML文件。 每次升级时,我们需要先删除所有的YAML资源,然后重新创建新的资源。 这种方式存在以下问题: 服务中断:…...
Text-to-SQL将自然语言转换为数据库查询语句
有关Text-To-SQL方法,可以查阅我的另一篇文章,Text-to-SQL方法研究 直接与数据库对话-text2sql Text2sql就是把文本转换为sql语言,这段时间公司有这方面的需求,调研了一下市面上text2sql的方法,比如阿里的Chat2DB,麻…...
gin学习
gin学习笔记,不仅包含了基本的增删查改外,还包括参数传递,上传下载,模版、session与中间件等,方便收藏自习可用 文章目录 获得个请求get打印字符串get请求xmlget请求跳转http方法路由可以通过Context的Param方法来获取…...
【HarmonyOS NEXT】关键资产存储开发案例
在 iOS 开发中 Keychain 是一个非常安全的存储系统,用于保存敏感信息,如密码、证书、密钥等。与文件系统不同,Keychain 提供了更高的安全性,因为它对数据进行了加密,并且只有经过授权的应用程序才能访问存储的数据。那…...
高德终端技术总结:高可用架构如何练成?
前言 高德地图作为国民级应用,特别是出行场景的独特性,要确保在线导航高并发和交通安全级的超稳定性,这对技术团队提出异乎寻常的高要求,无论是终端、云端,还是“终端-云端”之间的连接,都必须实现“高可用…...
STM32八股【3】------RAM和片上FLASH
1、RAM和FLASH构成 1.RAM ┌──────────────────────────┐ │ 栈区 (Stack) │ ← 从RAM顶端向下扩展(存储局部变量、函数调用信息) │--------------------------│ │ 堆区 (Heap) │ ← …...
Apache Doris
Apache Doris介绍 Apache Doris 是一个基于 MPP 架构的高性能、实时的分析型数据库,以极速易用的特点被人们所熟知,仅需亚秒级响应时间即可返回海量数据下的查询结果,不仅可以支持高并发的点查询场景,也能支持高吞吐的复杂分析场…...
Debezium介绍
1.什么是Debezium Debezium 是一个开源的分布式平台,用于捕获数据库的变更事件(CDC,Change Data Capture)。它能够实时捕获数据库中的行级更改,并将这些更改作为事件流发送到消息中间件(如 Apache Kafka&a…...
奇迹科技:蓝牙网关赋能少儿篮球教育的创新融合案例研究
一、引言 本文研究了福建奇迹运动体育科技有限公司(简称‘奇迹科技’)如何利用其创新产品体系和桂花网蓝牙网关M1500,与少儿篮球教育实现深度融合。重点分析其在提升教学效果、保障训练安全、优化个性化教学等方面的实践与成效,为…...
Python散点图(Scatter Plot):高阶分析、散点图矩阵、三维散点图及综合应用
散点图:数据分析的利器 在数据分析领域,散点图是一种直观且强大的可视化工具,广泛应用于揭示变量间的相关性以及识别数据集中的异常值。本文将深入探讨散点图的这两种关键功能,并结合实际案例与Python代码示例,带您全面了解散点图的应用。 一、散点图如何展示变量间的相…...
计算机网络层超全解析:从IP协议到路由算法
🌐 (专业详解生活化类比,逻辑一镜到底) 📖 网络层的核心使命 核心任务:在不同网络间为数据包选择最佳路径,实现端到端通信。 类比:快递公司总部(网络层)根据…...
RoboVQA
RoboVQA:面向机器人技术的多模态长时推理 摘要 我们提出了一种可扩展、自下而上且具有内在多样性的数据收集方案,适用于中长时高级推理任务,其吞吐量比传统的自上而下分步收集方法高2.2倍。通过在3栋办公楼内使用多种实体(机器人、人类、使用抓取工具的人类)执行任意用…...
javascript语法入门
一、变量声明 在JavaScript中,可以使用var、let和const来声明变量。 javascript var name "张三"; let age 20; 二、数据类型 JavaScript中有7种基本数据类型:undefined、null、boolean、string、symbol、number,以及object。…...
前端字段名和后端不一致?解锁 JSON 映射的“隐藏规则” !!!
🚀 前端字段名和后端不一致?解锁 JSON 映射的“隐藏规则” 🌟 嘿,技术冒险家们!👋 今天我们要聊一个开发中常见的“坑”:前端传来的 JSON 参数字段名和后端对象字段名不一致,会发生…...
Java——ArrayList集合
ArrayList:基于动态数组实现,支持随机访问,适合频繁的随机访问操作,但在插入和删除元素时性能较差。 技术层面介绍 所属类库:ArrayList 位于 java.util 包中,它实现了 List 接口,因此具备 Lis…...
基于python+django的图书借阅网站-图书借阅管理系统源码+运行步骤
该系统是基于pythondjango开发的在线图书借阅管理系统。系统适合场景:大学生、课程作业、系统设计、毕业设计。 演示地址 前台地址: http://book.gitapp.cn 后台地址:http://book.gitapp.cn/#/admin 后台管理帐号: 用户名&…...
Flutter运行错误:UG! exception in phase ‘semantic analysis‘
最近在Mac Mini M4上通过Android Studio导入Flutter项目并运行,结果一直跑不起来,错误日志如下: 执行命令查看版本信息: flutter doctor --verbose通过输出信息Java version OpenJDK Runtime Environment (build 21.0.41242208…...
Python-docx库详解:轻松实现Word文档自动化生成与图片尺寸控制
Python-docx库详解:轻松实现Word文档自动化生成与图片尺寸控制 在现代办公自动化的浪潮中,文档处理是一项不可或缺的任务。Python作为一种强大的编程语言,提供了丰富的库来简化这些任务。其中,python-docx库是处理Word文档的有力…...
【NLP 42、实践 ⑪ 用Bert模型结构实现自回归语言模型的训练】
目录 数据文件 一、模型定义 1.模型初始化 代码运行流程 2.前向传播,计算损失 ⭐ 代码运行流程 二、加载语料 代码运行流程 三、 随机生成样本 代码运行流程 四、建立模型 五、采样策略选择 代码运行流程 六、模型效果测试 代码运行流程 七、模型训练 代码运行流程 …...
HTTPS
目录 一 HTTPS是什么 二 加密 三 加密方案 四 CA机构/证书 五 最终方案(对称密钥/非对称密钥/CA证书)和总体流程 一 HTTPS是什么 在应用层存在SSL,TLS(HTTP之下,传输层之上)加密/解密安全协议,如果HTTP经过这个协议,对端也走…...
electron框架(4.0)electron-builde和electron Forge的打包方式
----使用electron-builder打包(需要魔法) --安装electron-builder: npm install electron-builder -D--package.json中进行相关配置: {"name": "video-tools","version": "1.0.0","main&quo…...
SaaS系统的销售微服务与权限微服务边界设计
在设计SaaS系统的销售微服务与权限微服务的边界时,需要结合领域驱动设计(DDD)和微服务拆分原则,确保高内聚、低耦合。以下是结合微服务架构原则、多租户SaaS需求及权限管理场景的完整设计方案,整合了权限服务与销售服务…...
Unity-AI-Deepseek生成的生成模型代码
结果 能用,不是很理想,从左到右,分别是body,眼睛,演睫毛,手指套(如果你知道这是什么)结果不是很理想 (下面代码已包含,修复的切线只能传Vector3参数,Unity2022测试) 你们帮我看看…...
Django REST Framework 请求封装源码解析与实现流程
版本说明: Django: V4.2.20 Django Rest Framework: V3.15.2 一、核心封装流程示意图 #mermaid-svg-qXJLIa9Bx1TCiPSN {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-qXJLIa9Bx1TCiPSN .error-icon{fill…...
简介PyCDE:Python CIRCT Design Entry
简介PyCDE:Python CIRCT Design Entry 引言 在硬件设计和验证领域,随着设计复杂性的增加,传统的方法往往难以满足现代设计的需求。PyCDE(Python CIRCT Design Entry)作为CIRCT项目的一部分,旨在为硬件设计…...
Python实现deepseek接口的调用
简介:DeepSeek 是一个强大的大语言模型,提供 API 接口供开发者调用。在 Python 中,可以使用 requests 或 httpx 库向 DeepSeek API 发送请求,实现文本生成、代码补全,知识问答等功能。本文将介绍如何在 Python 中调用 …...
考研课程安排(自用)
文章目录 408数据结构(王道)计算机组成原理(王道)操作系统(王道)计算机网络(湖科大版) 数学一高等数学(微积分)线性代数和概率论 408 数据结构(王…...
Mybatis操作数据库(注解+xml两个方式)
文章目录 1.个人回顾2.关于mybatis注解的说明3.字段和属性不匹配的解决方案3.1第一个方案3.2第二个方案3.3第三个方案 4.xml路径配置5.xml里面的字段映射 1.个人回顾 刚刚翻看了一下自己的这个之前写的博客,上一次和这个javaee相关的博客还是去年写的,也…...
文心快码 使用体验与介绍
一、文心快码的核心作用 文心快码是百度基于文心大模型开发的智能代码助手,核心价值包括: 代码生成与补全 通用开发:根据注释生成HTML/CSS/JS、Python、Java等代码C专项:生成类定义、STL容器操作、智能指针代码(如st…...
区块链交易
文章目录 交易准备合约和代码逻辑合约compile.jsindex.js 运行 交易 项目来自https://github.com/Dapp-Learning-DAO/Dapp-Learning/blob/main/basic/02-web3js-transaction/README-cn.md 本项目包含对交易进行签名,发送,接收交易回执,验证…...