我看过presentation还有一个关于共享缓冲区工作的问题。如幻灯片 16 所示,当服务器处理传入请求时,postmaster
进程调用 fork()
创建一个子进程来处理传入请求。这是那里的一张照片:
因此,我们拥有了 postmaster 进程的完整副本,除了它的 pid
。现在,如果子进程更新一些属于共享内存的数据(放入共享缓冲区,如幻灯片 17 所示),我们需要让其他线程知道这些更改。图片:
同步过程是我不明白的。任何进程都拥有共享内存的副本,并且在复制时不知道另一个线程是否会写入 某些内容到它的共享内存副本。如果在通过调用 fork()
创建了 proc1
之后,稍后创建了另一个进程 proc2
并开始将一些内容写入其副本共享内存。
问题: proc1
如何知道如何处理被 proc2< 修改的共享内存部分
?
最佳答案
要理解的关键是使用了两种不同类型的内存共享。
一种是fork()
(没有exec()
)使用的写时复制共享,子进程继承父进程的内存和状态。在这种情况下,当 child 或 parent 修改任何内容时,将分配修改后的内存页的新私有(private)副本。因此,子级看不到父级在 fork()
之后所做的更改,父级也看不到子级在 fork()
之后所做的更改。同龄 child 也看不到彼此的变化。就内存而言,它们都是孤立的,它们只是共享一个共同的祖先。
该内存显示在图表的Program (text)
、data
和stack
部分。
由于这种隔离,PostgreSQL 还使用 POSIX 共享内存——或者,在旧版本中,系统 V 共享内存。这些是映射到地址范围的显式共享内存段。每个进程看到相同的内存,并且它不是写时复制。它是完全读/写共享的。
这就是图中紫色“共享内存”部分所示的内容。
POSIX 共享内存用于锁定、shared_buffers 等进程间通信。不是从 fork()
ing 继承的内存。
虽然来自fork
的内存通常是写时共享的,但这实际上是一个操作系统实现细节。操作系统可以选择根本不共享它,并在 fork
时为子进程立即复制父进程的整个地址空间。写时复制共享真正相关的唯一方法是查看 top
等
当 PostgreSQL 提到“共享内存”时,它总是在谈论映射到每个进程地址空间的 POSIX 或 System V 共享内存块。不是来自 fork()
的写时复制共享。
关于sql - 了解 postgreSQL 共享内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32930787/