Linux操作系统:写时复制技术

了解COW

写时复制(copy-on-write,又称COW)是一种可以推迟甚至免除拷贝数据的技术。

Linux的fork()使用写时拷贝(copy-on-write)内存页实现。fork后父子进程两者的虚拟内存地址不同,但通过页表映射关系,最终物理地址是同一个,子进程的代码段、数据段、堆栈都是指向父进程的物理空间。当父子进程中某段数据修改时,子进程才真正分配物理空间。

效果

1.减少拷贝次数,降低开销。
在页根本不会被写入的情况下—举例来说,fork()后立即调用exec()—它们就无需复制了。fork()的实际开销就是复制父进程的页表以及给子进程创建唯一的进程描述符。在一般情况下,进程创建后都会马上运行一个可执行的文件,这种优化可以避免拷贝大量根本就不会被使用的数据(地址空间里常常包含数十兆的数据)。

COW应用场景

redis的COW

redis中借助了fork内部的COW,达到降低内存拷贝的目的

redis运行时通常是单进程的,在bgsave或bgrewriteof时会fork出一个进程, 如果子进程存在期间发生大量写操作,会出现很多缺页异常,导致耗费不少性能在内存复制上

为了尽量避免子进程存在期间触发rehash操作(rehash会对原key所有数据进行迁移),此时redis会将负载因子阈值提高到5,避免不必要的内存拷贝

C++

实际上COW技术不仅仅在Linux进程上有应用,其他例如C++的String在有的IDE环境下也支持COW技术,即例如:

1
2
string str1 = "hello world";
string str2 = str1;

之后执行代码:

1
2
str1[1]='q';
str2[1]='w';

在开始的两个语句后,str1和str2存放数据的地址是一样的,而在修改内容后,str1的地址发生了变化,而str2的地址还是原来的,这就是C++中的COW技术的应用,不过VS2005似乎已经不支持COW。