Postgresql启动后申请两段内存,在启动时会判断系统支持情况,默认是使用mmap申请共享内存。
- mmap申请匿名内存块,直接继承给子进程使用,头部放PGShmemHeader结构记录使用情况。
- 《Linux内存映射函数mmap与匿名内存块》
- ipc的共享内存,只申请PGSharedMemoryCreate大小。
- 《Linux共享内存与子进程继承》
Postgresql的共享内存在9.2以后就是使用mmap申请的了,在少数情况下使用ipc的共享内存。
下面在CreateSharedMemoryAndSemaphores中初始化的数据结构,都是在父进程中初始化好,直接继承给子进程使用的。
mmap内存块使用情况:
代码语言:javascript复制0x2aaaaac00000[mmap] ----------------------- <-- ShmemSegHdr / ShmemBase
PGShmemHeader
int32 magic;
pid_t creatorPID;
Size totalsize;
Size freeoffset;
dsm_handle dsm_control;
void *index;
freeoffset=56 -> - - - - - - - - - - - - <-- sharedSemas(信号量:一个进程一个sem_t)
PGSemaphoreData(128B)
PGSemaphoreData
...(2035 5)
PGSemaphoreData
freeoffset=261176 -> - - - - - - - - - - - - <-- ShmemLock(spinlock:一个slock_t)
slock_t(1B)
(只用1B但按8B对齐)
freeoffset=261184 - - - - - - - - - - - - <-- ShmemVariableCache(关键全局计数器)
VariableCache
freeoffset=261376 - - - - - - - - - - - -
LWLOCK
...
freeoffset=288256 - - - - - - - - - - - - <-- ShmemIndex(key:48B/val:ShmemIndexEnt)
ShmemInitHash("ShmemIndex") (共享内存索引哈希表)
(哈希表初始化好了,后面用ShmemInitStruct申请共享内存)
(前面使用ShmemAlloc申请)
(后面使用ShmemInitStruct调用ShmemAlloc申请)
freeoffset=298880 - - - - - - - - - - - - <-- XLogCtl(XLOG和写BUFFER)
XLogCtlData
...
freeoffset=4507136 - - - - - - - - - - - - <-- ControlFile(控制文件)
ControlFileData
freeoffset=4507520 - - - - - - - - - - - - <-- SharedStats
XLogPrefetchStats
freeoffset=4507648 - - - - - - - - - - - -
...
...
...
...
...
0x2aaabea00000 ----------------------- [mmap] <-- ShmemEnd
...
IPC的共享内存:
代码语言:javascript复制在当前例子中,IPC的共享内存只申请了一个PGShmemHeader的空间,没有其他空间可以使用。
0x7fc90a686000 ----------------------- [shmget] <-- InternalIpcMemoryCreate / UsedShmemSegAddr
PGShmemHeader
-----------------------
其中
- freeoffset:在PGShmemHeader结构中记录空闲起始位置
- ShmemIndex
- 这个步骤会创建哈希表,key是48B的字符串,val就是共享内存的位置,相当于索引表。
- 在这个步骤前,直接使用ShmemAlloc申请共享内存,调整freeoffset位置
- 在这个步骤后,使用ShmemInitStruct申请共享内存,先在哈希表中创建一个索引条目,在使用ShmemAlloc调整freeoffset位置。