copy-on-write 原理

      简单来说,在复制一个对象时并不是真的在内存中把原来对象的数据复制一份到另外一个地址,而是在新对象的内存映射表中指向同原对象相同的位置,并且把那块内存的Copy-On-Write位设为1. 在对这个对象执行读操作的时候,内存数据没有变动,直接执行就可以。在写的时候,才真正将原始对象复制一份到新的地址,修改新对象的内存映射表到这个新的位置,然后往这里写。

      这个技术需要跟虚拟内存和分页同时使用,其好处是在复制对象的时候因为并不是真的复制,而只是建了一个“指针”,因而大大提高性能。但这并不是一直成功的,前提是在复制新对象之后,进行的写操作只是在一小部分的内存分页上,大部分分页不会用到或者只是读取。不然会产生大量的分页错误,得不偿失。

      但对于fork 和 exec, 这又是另外一回事。 因为fork 之后一般会跟一个 exec, 将进程空间完全替换。 因此在fork上采用Copy-On-Write, 会省去一次不必要的进程空间复制。

      fork 和 exec 调用概念:

      学过C的都知道,Unix下某个进程的内存分成三部分:代码段,堆栈段,数据段。代码段用来存放程序运行的代码,堆栈段用来存放子程序的局部变量,数据段用来存放全局变量。这在perl 里也是一样的。

      perl的fork调用,跟C一样,当发生fork调用时,实际上发生如下事:

      父进程将代码段,堆栈段,数据段完全复制一份给子进程。也就是说,在子进程运行之初,它拥有父进程的一切变量和句柄。例如,父进程申请了某个hash表,那这个hash表也会被子进程拥有。然而,一旦子进程开始运行,它的数据段和堆栈段就在内存里完全和父进程分离了,即两个进程间不再共享任何数据。例如,前面所说的hash表,虽然子进程从父进程处继承了这个数据结构,但子进程写往hash里的数据,不会被父进程访问到。在shell里用ps命令,可以看到2个独立运行的进程。通常你kill掉1个,不会影响另一个运行。

      那么父进程和fork出来的子进程如何通信呢?父进程和子进程间的通信有多种方法,最常见的是信号,另外还有管道,Socket,消息队列等。而2个进程间共享数据的办法,可以用线程或共享内存。

      如果大概明白了fork,那么exec就容易理解了。一个进程一旦调用exec类函数,它本身就“死亡”了,系统把代码替换成新程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段和堆栈段,唯一留下的,就是进程号,即,对系统而言,还是同一个进程,不过已经是另一个程序了。

      在perl里,调用exec后,原进程就完全消失了,那它就不会从新进程接收到任何返回值,除非新进程意外终止,原进程会接收到错误值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值