我看了presentation,仍然有一个关于共享缓冲区工作的问题。如幻灯片16所示,当服务器处理传入请求时,postmaster
进程调用fork()
来创建一个子进程来处理传入请求。下面是其中的一张图片:
所以,我们有了postmaster进程的整个副本,除了它的pid
。现在,如果子进程更新了一些属于共享内存的数据(放入共享缓冲区,如幻灯片17所示),我们需要其他线程知道这些变化。图片:
同步过程是我不理解的。任何进程都拥有共享内存的副本,并且在复制时它不知道另一个线程是否会***向其共享内存的副本写入***内容。如果在通过调用fork()
创建proc1
之后,稍后创建另一个进程proc2
,并开始向其共享存储器的副本中写入一些内容。
***问题:***proc1
如何知道如何处理proc2
正在修改的共享内存部分?
2条答案
按热度按时间rlcwz9us1#
需要理解的关键是 * 使用了两种不同类型的内存共享 *。
一种是
fork()
使用的写时复制共享(没有exec()
),其中子进程继承父进程的内存和状态。在这种情况下,当子进程或父进程修改任何内容时,修改后的内存页的一个新的私有副本被分配。所以子进程看不到父进程在fork()
之后所做的更改,父进程也看不到。t看到子节点在fork()
之后所做的更改。对等子节点也不能看到彼此的更改。就内存而言,它们都是孤立的,它们只是共享一个共同的祖先。该内存就是图中
Program (text)
、data
和stack
部分所示的内存。由于这种隔离,PostgreSQL * 也 * 使用POSIX共享内存-或者,在旧版本中,系统V共享内存。这些是显式共享内存段,Map到一系列地址。每个进程看到相同的内存,并且它 * 不是 * 写时复制。它是完全读/写共享的。
这就是图中紫色的“共享内存”部分所显示的内容。
POSIX共享内存用于进程间通信,用于锁定,共享缓冲区等。不是从
fork()
ing继承的内存。虽然
fork
的内存通常是共享的写时拷贝,但这实际上是操作系统实现的细节。操作系统可以选择根本不共享它,而是在fork
时间为子进程立即复制父进程的整个地址空间。写时拷贝共享真正相关的唯一方式是在查看top
等时。当PostgreSQL提到“共享内存”时,它总是指Map到每个进程地址空间的POSIX或System V共享内存块,而不是
fork()
的写时复制共享。jtw3ybtb2#
我不知道这种特殊情况,但通常在linux和大多数其他操作系统中,为了加快创建新进程的速度,当一个进程要求操作系统创建一个新进程时,OS会以最低要求创建新进程。(特别是在DB应用程序中)并与子程序共享大部分父内存空间。现在,当子程序想要修改共享内存的某一部分时,操作系统使用COW(写时复制)概念,并为子进程创建该部分内存的新副本。因此,这部分内存变得特定于子进程,不再与父进程共享。