有用的"Copy-On-write",写时复制

写时复制和写时拷贝是一个意思

写时复制是一种策略,并不是Linux独有的,如果你正在设计某个系统架构,也可以参考这种思想。

写时复制的英文解释如下

Copy-on-write (sometimes referred to as "COW") is an optimization strategy used in computer programming. 

写时复制是计算机的一种优化策略,也可以说是优化机制,是计算机的优化策略并没有错,但是这种策略是人想出来的。

The fundamental idea is that if multiple callers ask for resources which are initially indistinguishable, you can give them pointers to the same resource. 

它的基本思想是,如果有多个调用「callers」,「也可以说是多个进程,多个线程,Linux里面只关心任务就好了」请求同一个难以区分的资源,你可以让他们指向同一个资源指针。

This function can be maintained until a caller tries to modify its "copy" of the resource, at which point a true private copy is created to prevent the changes becoming visible to everyone else.All of this happens transparently to the callers. 

直到有其中一个调用者,试图更改这个两个进程都指向的资源,系统才会分配一个真正的资源「可以认为是物理地址」给这个调用者。这个过程对所有人可见

The primary advantage is that if a caller never makes any modifications, no private copy need ever be created.

如果调用方,也就是拥有相同资源指针的两个进程,都不对资源进行修改,那么就不需要生产一个副本资源。

写时复制的缩写是「COW,奶牛」,但是实际上它跟奶牛没有任何关系。

举个例子说明

假设你是一个酒店老板,马云和任正非在你们酒店订了2020年11月20号的房间,你当时看到酒店还没有住满,所以就给他们下发了一个订购成功的返回值。

如果是程序,在内存充分的情况下,创建进程也就成功了。

然后,你其实不需要马上给马云和任正非安排具体的房间,因为他们俩都还没有到酒店开房。

假设晚上他们过来开房了,你就需要给他们开辟这个房间「也可以认为是资源」,给他们晚上做他们想做的事情。

如果他们一直都不来,那你就不用给他们开房,也就不实际占用你的房间。

fork()函数和写时复制

fork()函数是一个神奇的函数,调用一次,会返回两次,在这个过程中子进程和父进程是共享一个内存空间的。

#include <unistd.h>
#include <stdio.h>

int main()
{
 int pid = fork();
 if(pid == -1){
  return (-1);
 }

 if(pid > 0){
  printf("Hi,Father Pid:%d\n",getpid());
  return (0);
 } else {
  printf("Hi,Child Pid:%d\n",getpid());
  return (0);
 }
}


-- 程序输出:

weiqifa@bsp-ubuntu1804:~/linux$ gcc -o copy copy-for-write.c 
weiqifa@bsp-ubuntu1804:~/linux$ ./copy
Hi,Father Pid:36320
Hi,Child Pid:36321

-- 然后我加入一个资源

#include <unistd.h>
#include <stdio.h>

int main()
{
 char c = 'a';

 int pid = fork();
 if(pid == -1){
  return (-1);
 }

 if(pid > 0){
  c = 'v';
  printf("Hi,Father Pid:%d &c:%p c:%c\n",getpid(),&c,c);
  return (0);
 } else {
  printf("Hi,Child  Pid:%d &c:%p c:%c\n",getpid(),&c,c);
  return (0);
 }
}

-- 程序输出:

weiqifa@bsp-ubuntu1804:~/linux$ gcc -o copy copy-for-write.c && ./copy
Hi,Father Pid:36518 &c:0x7ffc41acae93 c:v
Hi,Child  Pid:36519 &c:0x7ffc41acae93 c:a

我们可以看到,父进程中我们对资源 c 进行了修改,并打印了资源的地址和值,然后我们在子进程中也打印资源的值。

可以看到,父进程先执行修改 c 的值,并打印 c 的值 是 v

子进程运行,打印 的值,c 的值是 原理的初始化值 a

也就是说这个过程发生了写时复制,在父进程种给 分配了物理内存区别于子进程。

创建进程没有发生写时拷贝的情况

没有发生写时复制的情况

发生了写时复制的情况

推荐阅读:

    专辑|Linux文章汇总

    专辑|程序人生

    专辑|C语言

嵌入式Linux

微信扫描二维码,关注我的公众号 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值