如何给指定地址空间拍一个快照



需求来自于,我希望可以对 lua 虚拟机中的内容做持久化,却又不希望 stop the world 。这需要利用 os 的功能,对内存做一个快照。简单的 fork 就可以达到快照的要求,但是 fork 会快照整个进程的地址空间,这不是我想要的。

这两天和几位同学讨论了各种方案,比如 memcpy ,比如 fork+exec 传递 shm_open 的 fd , fork 后 munmap 不用的区域等等。最后我认为如下方案相对更满意一些。我并没有实现出来, 写 blog 只是做个记录。

在启动主进程之初,把需要快照的地址空间用 mmap 设置好。使用 MAP_SHARED 方式。这个时候,子进程是干净的,占用的物理内存很小。这个子进程休眠待命。

在主进程中创建 lua state ,自定义 alloc ,指向前面 mmap 的空间。这里这样做的前提是,确定 lua state 占用的空间不会超过预留的空间。

当主进程想做 lua state 的 snapshot ,通知待命子进程。再由子进程 fork 一份出来,并使用 minherit 把之前 mmap 的地址段修改为 MAP_PRIVATE 的,至此,快照完成。

做完快照的进程,可以把 lua state 指针指向那块地址空间里,按部就班的做持久化工作了。

这里需要使用一个锁,保证主进程下达 snapshot 操作指令后一直等待最终持久化进程做完 minherit 的修改完成,这样才确保 snapshot 的时刻是确定的。


这样做是比直接 fork 要繁琐需要,适合 lua state 占用的内存仅仅是主进程数据区的一小部分的情况。且持久化时间较长,如此可回避 fork 后,大量不必要的内存页复制。

如果整个系统都由自己设计,也可以 fork 后调用 munmap 去掉显然不再需要的数据区,不过这需要对进程内其它模块有足够了解,我比较怀疑可以做的好。


我在这方面经验不足,或许还有更简单有效的方案。


流程如下:
1,主进程停止工作
2,主进程通知子进程进行内容持久化
3,子进程创建子进程2;
4,子进程2 minherit 备份内存为Private;
5,主进程继续执行工作;
6,子进程2 进行持久化工作,该过程耗时比较长;
以上过程从1~5主进程停止了工作;
该设计使得耗费时间成的持久化工作在其他进程执行;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值