因此,除了pid之外,我们拥有postmaster进程的完整副本.现在,如果子进程更新属于共享内存的某些数据(放入共享缓冲区,如幻灯片17所示),我们需要其他线程知道这些更改.图片:
同步化过程是我不明白的.任何进程都拥有共享内存的副本,并且在复制时不知道另一个线程是否会将某些内容写入共享内存的副本.如果在通过调用fork()创建proc1之后,稍后会创建另一个进程proc2并开始在其共享内存副本中写入内容.
问题:proc1如何知道如何处理proc2修改的共享内存部分?
一个是fork()使用的copy-on-write共享(没有exec()),其中子进程继承父进程的内存和状态.在这种情况下,当子或父修改任何内容时,将分配修改的内存页面的新私有副本.因此,在fork()之后,子节点看不到父节点所做的更改,而父节点在fork()之后看不到子节点所做的更改.同龄儿童也看不到彼此的变化.就记忆而言,它们都是孤立的,它们只是共享一个共同的祖先.
由于这个问题,Postgresql也使用POSIX共享内存 – 或者在旧版本中使用系统V共享内存.这些是显式共享的内存段,映射到一系列地址.每个进程都看到相同的内存,并且它不是写时复制.它完全读/写共享.
这是图中紫色“共享内存”部分所示的内容.
POSIX共享内存用于进程间通信,用于锁定,共享缓冲区等.不是从fork()继承的内存.
虽然来自fork的内存通常是共享写时复制,但这实际上是一个操作系统实现细节.操作系统可以选择不共享它,并在分叉时立即复制父项的整个地址空间.写拷贝共享真正相关的唯一方法是查看顶部等.
当Postgresql引用“共享内存”时,它总是在谈论映射到每个进程的地址空间的POSIX或System V共享内存块.不是fork()的copy-on-write共享.