【Linux】写时拷贝技术COW (copy-on-write)

文章目录

  • Linux写时拷贝技术(copy-on-write)
    • 进程的概念
      • 进程的定义
        • 进程和程序的区别
        • PCB的内部构成
    • 程序是如何被加载变成进程的?
      • 写时复制(Copy-On-Write, COW)
        • 写时复制机制的原理
        • 写时拷贝的场景
      • fork与COW
      • vfork与fork


Linux写时拷贝技术(copy-on-write)

在了解写时拷贝技术之前我们得先知道进程

进程的概念

进程的定义

肤浅的来说,加载到内存中的程序就叫做进程。但这并不完善。

运行中的系统存在大量的进程,操作系统该如何管理这些进程呢?仍然是先描述再组织。

进程在形成之初,操作系统就会为其创建进程控制块 PCB。进程控制块PCB用于描述进程,其中存储着进程的所有属性。

Linux 系统中,PCB 就是一个名为task_struct的结构体。

Linux 查看进程的命令:

$ ps axj | head -1 && ps axj | grep 'myproc'PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
25486 29733 29733 25486 pts/0    29733 S+    1003   0:00 ./myproc # 正在运行的myproc进程

启动程序的本质,就是在内存上创建进程。

进程和程序的区别
  • 程序本质就是文件,是编译生成的二进制可执行文件。
  • 程序被加载到内存中,系统自动为其创建PCB,以管理该进程。故进程是程序的代码数据与进程相关内核数据结构的总和

操作系统在处理进程时, 不是直接操作程序而是读写PCB,因为PCB中含有程序的所有属性。也就是说,进程管理与进程对应的程序毫无关系,只与进程的PCB强相关

PCB的内部构成

task_struct结构

  • 进程编号 —— 每个进程都有编号或称标识符,也就是 PID,具有唯一性用来区别于其他进程。
  • 进程状态 —— 包括进程退出时的退出码、退出信号、任务状态等。
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);

程序是如何被加载变成进程的?

首先,程序通过编译器转换为目标代码,并由链接器与库函数链接,形成可执行文件。此时程序内部已分配逻辑地址,但尚未映射至物理内存。当程序被执行时,操作系统将其从存储介质加载至内存,并进行逻辑地址到物理地址的映射,这一映射关系存储于页表中。

在C/C++中,地址并不是内存物理上的地址,而是操作系统提供的虚拟地址。操作系统不允许直接读取物理内存。虚拟地址在不同进程中是相同的,但物理地址是不同的。例如,当使用fork函数创建子进程时,父进程的栈空间中的变量并不会直接复制到子进程中,而是通过写时拷贝的机制。这意味着,当父进程或子进程尝试修改这些变量时,才会发生真正的复制操作,从而保证了父子进程间的数据独立性。

如果想要执行你书中(A程序)第8页的一段代码,那就由一个人,我们叫他管理员(操作系统),管理员把这一页程序复制到这本速读书(物理地址空间)的某个空白页上,比如第1页,同时记录这个映射关系(A程序的第8页放在了这本书的第1页),如果B程序也要执行第8页中的一段代码(虚拟地址相同),也需要由那个人把这一页复制到这本速读书的某个空白页上,比如第二页,并将映射关系记录在映射表上。这种情况就是虚拟地址相同,但被放在了不同的物理地址上。

在这里插入图片描述

写时复制(Copy-On-Write, COW)

写时复制(Copy-on-Write, COW)是一种优化策略。其主要思想是,当多个调用者(callers)请求相同资源(如内存或磁盘上的数据存储)时,他们会共享相同的指针指向同一资源。只有当某个调用者尝试修改资源内容时,系统才会为该调用者创建一份专用副本(private copy)。这种策略对其他调用者是透明的,只有在修改资源时才会创建副本,因此在调用者仅进行读取操作时可以共享同一份资源。

写时复制机制的原理

进程具有独立性,为了保证进程间数据独立,进程间不相互干扰,会有数据的写时拷贝,得到一张新的页表。在上面的程序中,变量的物理地址实际就不同了,因此数据也是不同的。

img

写时拷贝技术实际上是运用了一个 “引用计数” 的概念来实现的。在开辟的空间中多维护四个字节来存储引用计数。
有两种方法:

  • 多开辟四个字节(pCount)的空间,用来记录有多少个指针指向这片空间。
  • 在开辟空间的头部预留四个字节的空间来记录有多少个指针指向这片空间。

当我们多开辟一份空间时,让引用计数+1,如果有释放空间,那就让计数-1,但是此时不是真正的释放,是假释放,等到引用计数变为 0 时,才会真正的释放空间。如果有修改或写的操作,那么也让原空间的引用计数-1,并且真正开辟新的空间。

linux 下的 fork() 就是用的写时拷贝技术,引用计数不光在 string 这里用到,还有智能指针 shared_ptr 也用到了引用计数来解决拷贝问题。

写时拷贝的场景

虚拟内存管理中的写时复制

  • 在虚拟内存管理中,页面通常被标记为只读。当某个进程尝试向内存写入数据时,内存管理单元(MMU)会抛出一个异常。内核在处理该异常时,会为该进程分配一份新的物理内存并复制数据到该内存中,然后重新执行写操作。

数据存储中的写时复制

  • Linux等操作系统的文件管理系统使用了写时复制策略。
  • 数据库服务器也通常采用写时复制策略,为用户提供快照(snapshot)。

软件应用中的写时复制

  • C++标准程序库中的std::string类,在C++98/C++03标准中允许写时复制策略,但在C++11标准中为了提高并行性取消了这一策略。GCC从版本5开始,std::string不再采用COW策略。

fork与COW

fork是Linux系统中用于创建新进程的系统调用。在传统的fork实现中,子进程会完全复制父进程的地址空间,包括数据段、堆、栈和只读的代码段。这种复制操作可能会消耗大量的时间和内存资源。

为了优化这一过程,现代操作系统引入了写时复制(Copy-On-Write, COW)策略。在fork之后,子进程和父进程共享数据段、堆和代码段,但内核会将这些共享区域的访问权限设置为只读。如果任何一个进程尝试修改这些共享区域,内核会为该进程创建该区域的一个私有副本,这个过程称为“写时复制”。这样,只有在实际需要修改数据时,才会发生内存复制,从而节省了内存空间和复制时间。

vfork与fork

vfork是另一种用于创建新进程的系统调用,它与fork的主要区别在于,vfork不会复制父进程的地址空间,而是让子进程直接在父进程的地址空间中运行,直到子进程调用execexit。这意味着子进程在调用execexit之前,对父进程地址空间中的任何修改都会影响到父进程。

vfork的设计初衷是为了在子进程立即调用exec执行新程序的情况下,避免不必要的地址空间复制。由于子进程不会访问父进程的地址空间,因此vfork可以更高效地创建新进程。

然而,vfork的使用需要非常小心,因为子进程和父进程共享地址空间,这可能导致数据竞争和不确定的行为。因此,vfork通常在子进程调用execexit后立即返回,以避免潜在的问题。

vfork与fork的对比

  • fork通过写时复制技术优化了进程创建过程,允许父进程和子进程共享地址空间,直到需要修改时才进行复制。
  • vfork则是在子进程立即调用execexit的情况下,避免复制父进程的地址空间,直接在父进程的地址空间中运行子进程。

两者都是创建新进程的方法,但fork更为通用,而vfork则是在特定场景下的一种优化手段。由于vfork可能带来的风险,现代操作系统中fork通常已经足够高效,而vfork的使用则越来越少。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VUE3 学习笔记(十)查看vue版本

命令&#xff1a; npm list vue(空) (在项目的根目录下执行以下命令即可查看项目所使用的vue版本) npm list vue version(空) npm info vue (全局查看vue版本号&#xff0c;详细) npm list vue -g(全局查看vue版本号&#xff0c;简单) npm view vue version(查看项目依赖的vue…

开源博客项目Blog .NET Core源码学习(26:App.Hosting项目结构分析-14)

后台管理页面的系统管理下主要包括用户管理、角色管理、按钮管理和菜单管理&#xff0c;其中创建用户时要指定角色&#xff0c;创建角色时需指定菜单权限&#xff0c;按钮管理也是基于各菜单项进行设置&#xff0c;只有菜单管理相对独立&#xff0c;因此本文学习并分析App.Host…

蓝桥杯【第15届省赛】Python B组 32.60 分

F 题列表越界访问了……省一但没什么好名次 测评链接&#xff1a;https://www.dotcpp.com/oj/train/1120/ C 语言网真是 ** 测评&#xff0c;时间限制和考试的不一样&#xff0c;E 题给我整时间超限&#xff1f; A&#xff1a;穿越时空之门 100&#x1f3c6; 【问题描述】 随…

使用梦畅闹钟,结合自定义bat、vbs脚本等实现定时功能

梦畅闹钟-每隔一段时间运行一次程序 休息五分钟bat脚本&#xff08;播放音乐视频&#xff0c;并锁屏&#xff09; chcp 65001 echo 回车开始休息5分钟 pause explorer "https://www.bilibili.com/video/BV1RT411S7Tk/?p47" timeout /t 3 /nobreak rundll32.exe use…

什么是SSL证书?如何选择SSL证书?

在浏览网站的时候&#xff0c;你会不会有这样一些疑问。 为什么有的网站是http://开头&#xff0c;有的却是https://&#xff1f;它们有什么区别吗&#xff1f; 经常访问的网站&#xff0c;浏览器突然提示“安全证书过期”&#xff0c;提醒你不要浏览该网址&#xff1f; 这一切…

Debug-010-git stash的用法及使用场景

问题原因&#xff1a; 其实也不是最近&#xff0c;就是之前就碰到过这个问题&#xff0c;那就是我正在新分支开发新功能&#xff0c;开发程度还没有到可以commit的程度&#xff0c;我不想提交(因为有些功能没有完全实现&#xff0c;而且没有自测的话很容易有问题&#xff0c;提…

ICML 2024 时空数据(Spatial-Temporal)论文总结

2024ICML&#xff08;International Conference on Machine Learning&#xff0c;国际机器学习会议&#xff09;在2024年7月21日-27日在奥地利维也纳举行 &#xff08;好像ICLR24现在正在维也纳开&#xff09;。 本文总结了ICML 24有关时空数据(Spatial-temporal) 的相关论文…

Golang并发编程-协程goroutine任务取消(Context)

文章目录 前言一、单个任务的取消二、 所有任务取消三、Context的出现Context的定义Context使用 总结 前言 在实际的业务种&#xff0c;我们可能会有这么一种场景&#xff1a;需要我们主动的通知某一个goroutine结束。比如我们开启一个后台goroutine一直做事情&#xff0c;比如…

【小程序八股文】系列之篇章二 | 小程序的核心机制

【小程序八股文】系列之篇章二 | 小程序的核心机制 前言三、微信小程序原理与运行机制简述一下微信小程序的原理微信小程序的双线程的理解为什么不采用浏览器多线程模式&#xff1f;为什么是双线程&#xff1f;&#xff08;出发点&#xff1a;安全&#xff0c;快速&#xff0c;…

Express 的 req 和 res 对象

新建 learn-express文件夹&#xff0c;执行命令行 npm init -y npm install express 新建 index.js const express require(express); const app express();app.get(/, (req, res, next) > {res.json(return get) })app.post(/, (req, res, next) > {res.json(retur…

论文精读-SRFormer Permuted Self-Attention for Single Image Super-Resolution

论文精读-SRFormer: Permuted Self-Attention for Single Image Super-Resolution SRFormer:用于单图像超分辨率的排列自注意 Params&#xff1a;853K&#xff0c;MACs&#xff1a;236G 优点&#xff1a; 1、参考SwinIR的RSTB提出了新的网络块结构PAB&#xff08;排列自注意力…

sky walking日志采集以及注意事项

文章目录 1&#xff0c;sky walking日志采集功能概述2&#xff0c;采集log4j2日志3&#xff0c;采集logback日志4&#xff0c;效果展示5&#xff0c;注意事项 1&#xff0c;sky walking日志采集功能概述 在介绍Sky walking日志采集功能之前&#xff0c;最好在系统学习一遍日志…

【医学AI|顶刊精析|05-25】哈佛医学院·告别切片局限:3D病理如何革新癌症预后

小罗碎碎念 先打个预防针&#xff0c;我写这篇推文用了两个多小时&#xff0c;这就意味着要读懂这篇文章不太容易&#xff0c;我已经做好反复阅读的准备了。不过&#xff0c;风险之下&#xff0c;亦是机会&#xff0c;读懂的人少&#xff0c;这个赛道就越值得押宝。 在正式阅…

【C语言】8.C语言操作符详解(3)

文章目录 10.操作符的属性&#xff1a;优先级、结合性10.1 优先级10.2 结合性 11.表达式求值11.1 整型提升11.2 算术转换11.3 问题表达式解析11.3.1 表达式111.3.2 表达式211.3.3 表达式311.3.4 表达式411.3.5 表达式5: 11.4 总结 10.操作符的属性&#xff1a;优先级、结合性 …

基于Keras的手写数字识别(附源码)

目录 引言 为什么要创建虚拟环境&#xff0c;好处在哪里&#xff1f; 源码 我修改的部分 调用本地数据 修改第二层卷积层 引言 本文是博主为了记录一个好的开源代码而写&#xff0c;下面是代码出处&#xff01;强烈建议收藏&#xff01;【深度学习实战—1】&#xff1a…

【spring】@ControllerAdvice注解学习

ControllerAdvice介绍 ControllerAdvice 是 Spring 框架提供的一个注解&#xff0c;用于定义一个全局的异常处理类或者说是控制器增强类&#xff08;controller advice class&#xff09;。这个特性特别适用于那些你想应用于整个应用程序中多个控制器的共有行为&#xff0c;比…

ctfhub中的SSRF的相关例题(下)

目录 URL Bypass 知识点 相关例题 数字IP Bypass 相关例题 方法一&#xff1a;使用数字IP 方法二&#xff1a;转16进制 方法三&#xff1a;用localhost代替 方法四&#xff1a;特殊地址 302跳转 Bypass ​编辑 关于localhost原理: DNS重绑定 Bypass 知识点&…

ant design pro 6.0搭建教程

一、搭建 环境&#xff1a; Node.js 18.16.1 ant design pro 6.0 注意&#xff1a;选择umi3时&#xff0c;使用node.js 18版本的会报错&#xff0c;可以实践一下&#xff0c;这里就不再进行实践了。 umi3需要版本是低于node.js 18的 node下载地址&#xff1a; https://nodejs.…

可重构柔性装配产线,为智能制造领域带来了新的革命性变革

随着科技的飞速发展&#xff0c;个性化需求逐渐成为市场的主导。在这个充满变革的时代&#xff0c;制造业正面临着前所未有的挑战和机遇。如何快速响应市场需求、提高生产效率、保证产品质量&#xff0c;成为每一家制造企业必须思考的问题。 在这样的背景下&#xff0c;富唯智…

免费插件集-illustrator插件-Ai插件-文本对象和文本段落互转

文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.总结 1.介绍 本文介绍一款免费插件&#xff0c;加强illustrator使用人员工作效率&#xff0c;进行文本对象和文本段落互转。首先从下载网址下载这款插件 https://download.csdn.net/download/m0_67316550/878…