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

嵌入式Linux

共 2438字,需浏览 5分钟

 ·

2020-11-15 06:51


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


写时复制是一种策略,并不是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 
#include 

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 
#include 

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
微信扫描二维码,关注我的公众号 
浏览 49
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报