Cow : copy on write
在Linux系统中,调用
fork
系统调用来创建子进程之后,一般是会立即执行exec()
函数,那么如果我们还是在fork()
之后将数据拷贝给子进程那么就会很浪费资源。
fork 并不会将父进程中的数据进行复制,而是共享数据。与父进程使用相同的页, 只有当父子进程更改了共享的数据的时候才会单独的将这一小块内容复制出来进行更改给调用者。在此之前,他们都是以 只读 的方式对资源进行共享。 这样就使得地址空间上的页会在实际发生写入的时候才进行,在页根本不会被写入的情况下不需要拷贝了(直接执行
exec()
)
复制页表&创建 fd给子进程
fork()之后,kernel把父进程中所有的内存页的权限都设为read-only,然后子进程的地址空间指向父进程。当父子进程都只读内存时,相安无事。当其中某个进程写内存时,CPU硬件检测到内存页是read-only的,于是触发页异常中断(page-fault),陷入kernel的一个中断例程。中断例程中,kernel就会把触发的异常的页复制一份,于是父子进程各自持有独立的一份。
Redis 中 在进行 RDB 的产生的时候使用 bgsave 进行快照的产生
其实就是使用了子进程进行RDB快照的生成, fork 了子进程之后对于主进程的内存数据是 共享的, 而且快照的记录同样也是 只需要读,那么互相都不影响的。
如果此时主进程需要修改数据中的某一块数据的话,就会发生cow。将修改了的数据单独拿出来给主进程进行修改操作, bgsave 还是可以继续吧原来的数据写到 RDB文件。
很快啊朗 能够没有其他不必要的消耗记录快照的同时还能支持主进程对数据的修改