如何给指定地址空间拍一个快照
需求来自于,我希望可以对 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 去掉显然不再需要的数据区,不过这需要对进程内其它模块有足够了解,我比较怀疑可以做的好。
我在这方面经验不足,或许还有更简单有效的方案。
Comments
Posted by: 风的博客 | (23) February 25, 2011 11:52 AM
Posted by: felix021 | (22) February 15, 2011 10:28 PM
Posted by: heyingstar | (21) February 14, 2011 09:00 PM
Posted by: a1406 | (20) February 9, 2011 09:03 AM
Posted by: Cloud | (19) February 5, 2011 12:36 AM
Posted by: xixi | (18) February 4, 2011 11:24 PM
Posted by: 电脑知识与技术博客 | (17) January 31, 2011 12:38 AM
Posted by: Cloud | (16) January 30, 2011 10:54 PM
Posted by: 云端孤鹜 | (15) January 30, 2011 05:37 PM
Posted by: yihuang | (14) January 30, 2011 12:06 PM
Posted by: Atry | (13) January 29, 2011 01:55 PM
Posted by: Atry | (12) January 29, 2011 01:53 PM
Posted by: royhu | (11) January 29, 2011 01:49 AM
Posted by: hackage | (10) January 28, 2011 10:43 PM
Posted by: Cloud | (9) January 28, 2011 10:39 PM
Posted by: xiao_ming | (8) January 28, 2011 08:47 PM
Posted by: zbz | (7) January 28, 2011 08:33 PM
Posted by: felix021 | (6) January 28, 2011 08:31 PM
Posted by: Cloud | (5) January 28, 2011 06:17 PM
Posted by: 天堂的隔壁 | (4) January 28, 2011 06:09 PM
Posted by: 大使 | (3) January 28, 2011 04:46 PM
Posted by: Cloud | (2) January 28, 2011 04:39 PM
Posted by: Sil | (1) January 28, 2011 04:17 PM