当前位置: 首页 > news >正文

#Linux内存管理# 浅析缺页中断中私有映射且发生写时复制COW的工作原理

案例背景

假设一个进程通过 mmap 系统调用映射了一个文件(data.txt),并设置 私有映射(MAP_PRIVATE)。随后进程尝试修改映射区的数据,此时触发写时复制(Copy-On-Write, COW)机制。

 

关键步骤解析

 

 1.初始文件内容

 

  data.txt 原始内容:

  | A | B | C | D |

 

  物理内存中的页缓存(Page Cache)存放文件内容:

  

  物理页1: [A, B]

  物理页2: [C, D]

  

 2.建立私有映射

 

 进程执行:

     

 void *addr = mmap(

    NULL, 

    4096, // 映射4KB

    PROT_READ | PROT_WRITE, // 可读写

    MAP_PRIVATE, // 私有映射

    fd, // data.txt的文件描述符

    0 // 文件偏移0

    );

 

 此时状态:

 

 进程的页表指向物理页缓存(页1和页2)。

 

 页表权限:设置为只读(即使指定了PROT_WRITE,内核会在COW前保持只读)。 

 

 3.读取数据(无COW)

 

 进程读取 addr[0](值为 A):

 

  直接访问物理页缓存(页1),无需复制。

  

  无缺页中断,读取速度高效。

  

 4.修改数据(触发COW)

 

 进程尝试修改数据:

 

 addr[0] = 'X'; // 尝试将A改为X 

 

 COW流程:

  

 步骤1:CPU检测到写操作,但页表权限为只读 → 触发 缺页中断。

    

 步骤2:内核分配新物理页(页3): 

 

  物理页3: [A, B] // 复制页1的内容

  

 步骤3:更新进程页表

 

  原虚拟地址指向 新物理页3(原页1不再直接映射)。

 

  页表权限改为 可读写。 

  

 步骤4:重新执行写操作,将页3的内容修改为:

  

  物理页3: [X, B] // A被改为X

  

 最终状态

 

     物理内存:

 

     页1(原始页缓存): [A, B] // 未被修改,仍供其他进程读

  页2: [C, D] // 未被访问,保持原样

  页3(COW新页): [X, B] // 进程私有副本 

  

  文件data.txt内容不变(仍为A,B,C,D)。

     

  进程看到的虚拟地址内容:[X, B, C, D]。

 

  

COW的核心机制

 

 步骤 内核操作 物理内存变化

 

 写操作触发中断 CPU检测到只读页的写操作 → 缺页中断 无变化

 

 分配新物理页 内核分配新页,复制原页内容 新增页3(内容复制自页1)

 

 更新页表 修改页表:指向新页 + 权限改为可读写 进程与页1解耦,绑定页3

 

 执行写操作 修改新页内容 页3内容更新(A→X)  

 

COW的优势

 

 1.节省内存

 

 未修改的页(如页2)保持共享,减少冗余复制。

 

 2.高效惰性复制

 

 仅在实际写入时触发复制,避免提前拷贝的开销。

 

 3.数据隔离

 

 进程修改不影响原始文件或其他进程(私有映射特性)。

 

 4.减少I/O

 

 写操作延迟到缺页中断时才处理,避免不必要的磁盘写入  

 

关键代码验证 

 

// 在修改数据后验证文件内容不变

printf("进程内存: %c\n", addr[0]); // 输出 'X'

lseek(fd, 0, SEEK_SET);

char file_buf[4];

read(fd, file_buf, 4);

printf("文件内容: %c\n", file_buf[0]); // 输出 'A' (未修改)

 

注意:私有映射的修改对文件不可见,对共享该文件的其他进程也不可见。

 

http://www.dtcms.com/a/324379.html

相关文章:

  • 《Qt————Tcp通讯》
  • 容器网络隔离测试于VPS服务器环境的桥接模式验证
  • Docker 详细介绍及使用方法
  • 【大智慧数据】心智开花的时候
  • 数字图像处理3
  • 三、k8s 1.29 之 安装1网络 / ikuai路由器虚拟机安装
  • 【嵌入式】Linux的常用操作命令(2)
  • 防御保护10
  • AI优化SEO关键词实战应用
  • Java数据结构——LinkedList
  • scanpy单细胞转录组python教程(一):不同形式数据读取
  • Python爬虫实战:研究BlackWidow,构建最新科技资讯采集系统
  • Shell脚本-条件判断语法格式
  • React Profiler
  • 【代码随想录day 15】 力扣 404. 左叶子之和
  • 【无标题】命名管道(Named Pipe)是一种在操作系统中用于**进程间通信(IPC)** 的机制
  • Ubuntu 安装 Elasticsearch
  • Ubuntu 安装 Kibana
  • WGS84 与 ITRF 坐标系的差异及转换算法详解
  • 进程状态+进程优先级+进程上下文切换解读
  • 不同hash加密类型的hashfile.txt文件
  • C# 中常用集合以及使用场景
  • 强制类型转换
  • AI 对齐:让人工智能与人类价值同频共振
  • JavaWeb——maven高级(5/5)-私服(私服的概念与作用、Maven 依赖的查找顺序、上传资源到私服的配置步骤、下载依赖配置条件)
  • 单链表专题---暴力算法美学(2)(有视频演示)
  • actuary notes[2]
  • 单调栈——数位删减
  • Go语言中切片(Slice)的拷贝
  • 自创论述类文本阅读:论温泉