一文弄懂写时复制(COW)

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

在这里插入图片描述

基本概念

写时复制是计算机编程里的一种优化策略。它的核心思想在于,进行数据修改操作时,并非马上复制整个数据对象,而是要等到真正需要修改数据的那个时刻才执行复制操作。这样做能够避免不必要的数据复制,进而提升系统性能,提高资源利用率。

工作原理
初始化

当多个进程或者线程共享同一个数据副本时,它们实际上都是指向同一块物理内存区域。在这个阶段,并不会进行数据的复制操作。

  • 多个进程/线程 --> 同一块物理内存区域(共享数据)
写操作触发

一旦其中某个进程或者线程需要对共享数据执行写操作,操作系统或者相关系统就会先复制一份该数据的副本。之后,让进行写操作的进程或线程在这个副本上进行修改,而其他进程或线程依旧使用原来的数据副本。

  • 要进行写操作的进程/线程 --触发复制–> 生成数据副本 --> 在副本上修改
  • 其他进程/线程 --> 继续使用原数据副本
应用场景
操作系统

在一些操作系统(例如 Linux)中,当使用 fork() 系统调用创建子进程的时候,就会运用写时复制技术。子进程和父进程会共享相同的物理内存页面,只有在其中一个进程对页面进行写操作时,才会复制该页面。这样能够减少内存的使用以及复制开销。

  • 父进程和子进程 --> 初始共享物理内存页面
  • 有写操作的进程 --> 触发页面复制

Linux下的COW

传统子进程创建方式的问题

在 Linux 系统中,fork() 系统调用会创建一个与父进程几乎完全相同的子进程(唯一不同的是进程 ID,即 pid)。按照传统做法,会直接把父进程的数据复制到子进程中。复制完成后,父进程和子进程的数据段与堆栈是相互独立的。

然而,从实际使用情况来看,子进程通常会执行 exec() 函数来实现自身的特定功能。这就意味着,若采用传统复制数据的方式,创建子进程时复制过去的数据很多时候是无用的,因为子进程执行 exec() 时,原有的数据会被清空。

Copy On Write 技术的引入

鉴于很多情况下复制给子进程的数据是无效的,于是就诞生了 Copy On Write(COW)技术。其原理较为简单:

  • fork 创建的子进程会与父进程共享内存空间。也就是说,只要子进程不对内存空间进行写入操作,内存空间中的数据就不会复制给子进程。这样一来,创建子进程的速度会非常快,因为无需进行数据复制,子进程直接引用父进程的物理空间即可。
  • 若在 fork 函数返回后,子进程立即执行 exec 加载一个新的可执行映像,那么就不会造成时间和内存空间的浪费。

换一种表达方式来理解:

  • fork 之后、exec 之前,父子进程使用相同的物理空间(内存区)。子进程的代码段、数据段和堆栈都指向父进程的物理空间,即两者的虚拟空间不同,但对应的物理空间是同一个。
  • 当父子进程中有对相应段进行更改的操作发生时,才会为子进程的相应段分配物理空间。
    • 若不执行 exec,内核会为子进程的数据段和堆栈段分配对应的物理空间(至此,父子进程拥有各自独立的进程空间,互不影响),而代码段则继续共享父进程的物理空间(因为两者的代码完全相同)。
    • 若执行 exec,由于父子进程执行的代码不同,子进程的代码段也会分配单独的物理空间。
初始状态
多进程共享数据
有写操作?
复制数据
写操作在副本进行
copy - on - write 的实现原理

fork() 之后,内核会将父进程中所有内存页的权限设置为只读(read - only),然后让子进程的地址空间指向父进程。当父子进程都只是对内存进行只读操作时,一切相安无事。但当其中某个进程要对内存进行写操作时,CPU 硬件会检测到该内存页是只读的,从而触发页异常中断(page - fault),进而陷入内核的一个中断例程。在内核的中断例程中,会将触发异常的页复制一份,这样父子进程就各自持有一份独立的该页数据。

文件系统

部分文件系统(像 Btrfs、ZFS)也采用了写时复制技术。当对文件进行修改时,不会直接覆盖原数据,而是把修改后的数据写入新的磁盘块。这样做可以提高数据的可靠性和恢复能力,同时也便于进行文件系统的快照和版本管理。

  • 修改文件 --> 不覆盖原数据,写入新磁盘块
  • 利于数据恢复、快照及版本管理
优缺点
优点
  • 减少了不必要的数据复制,提高了系统的性能和资源利用率。因为在多数情况下不需要马上复制大量数据,避免了额外的开销。
  • 在创建子进程或者进行数据共享时,可以快速完成操作。由于无需立即复制大量数据,能显著缩短操作时间。
缺点
  • 增加了系统的复杂度,需要额外的管理机制来处理数据的复制和共享。这可能会带来更多的代码编写和维护工作。
  • 在某些情况下,可能会导致内存使用量的增加。因为写操作会触发数据的复制,可能会使内存中存在多份数据副本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cider瞳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值