设为首页 加入收藏

TOP

PostgreSQL启动过程中的那些事七:初始化共享内存和信号一:初始化shmemIndex和信号(一)
2014-11-24 00:59:50 来源: 作者: 【 】 浏览:7
Tags:PostgreSQL 启动 过程 那些 初始 共享 内存 信号 shmemIndex
pg现在要初始化另一块内存——共享内存shared memory(以后shared memory有时会简写成shmem),在这块内存里,pg存放数据、锁、各种backend进程等。

1先上个图,看一下函数调用过程梗概,中间略过部分细节

\

初始化共享内存方法调用流程图

2计算shared memory大小

话说main()->…->PostmasterMain()->…->reset_shared(),在reset_shared()这个函数里,pg首先计算干xxx一堆事需要的内存大小size,然后分之。

首先我们看看都计算了哪些内存,估算使用动态哈希表管理共享内存需要的内存;计算数据池及管理需要的内存(根据shared_buffer);计算锁表需要的共享内存;计算xlog、clog需要的共享内存;计算共享进程、子事务、并发控制、轻量级锁、backend进程、后台写等需要的共享内存等,这些共享内存统统累加到size。计算shared memory共享内存代码如下:

size = 100000;

size =add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,

sizeof(ShmemIndexEnt)));

size =add_size(size, BufferShmemSize());

size =add_size(size, LockShmemSize());

size =add_size(size, ProcGlobalShmemSize());

size =add_size(size, XLOGShmemSize());

size =add_size(size, CLOGShmemSize());

size =add_size(size, SUBTRANSShmemSize());

size =add_size(size, TwoPhaseShmemSize());

size =add_size(size, MultiXactShmemSize());

size =add_size(size, LWLockShmemSize());

size = add_size(size,ProcArrayShmemSize());

size =add_size(size, BackendStatusShmemSize());

size =add_size(size, SInvalShmemSize());

size =add_size(size, BgWriterShmemSize());

size =add_size(size, BTreeShmemSize());

size =add_size(size, SyncScanShmemSize());

size =add_size(size, ShmemBackendArraySize());

2分配并初始化shared memory

计算好需要的共享内存大小size后调用PGSharedMemoryCreate()函数分配共享内存。PGSharedMemoryCreate()函数创建给定大小的共享内存段并初始化一个PGShmemHeader结构类型标准头,且给释放内存注册回调函数。如果发现死postgres段就回收,但是和非postgres内存段碰撞后pg不会失败。这儿的想法是检测和重用崩溃的postmaster或backend进程已经分配的key。

PGSharedMemoryCreate()分配内存是先根据postmaster进程端口号计算找一个空闲IPC key的起始值。接着调用InternalIpcMemoryCreate()函数,尝试根据给定IPC key调用shmget()函数创建共享内存段。如果给定key的内存段已经存在就失败返回NULL。如果成功,把该内存段attach到当前进程postmaster并返回该内存段地址。调用on_shmem_exit()函数注册detach和delete该段内存时的回调函数IpcMemoryDelete()和IpcMemoryDetach()到on_shmem_exit_list数组。

on_shmem_exit()函数注册函数到以ONEXIT 结构为元素的数组on_shmem_exit_list[MAX_ON_EXITS]中以供shmem_exit()函数执行时调用。ONEXIT 结构结构定义见下面。

static struct ONEXIT

{

void (*function)(int code, Datum arg);

Datum arg;

} on_proc_exit_list[MAX_ON_EXITS],on_shmem_exit_list[MAX_ON_EXITS];

接着调用RecordSharedMemoryInLockFile()函数把IPC key和shmid记录到postmaster.pid文件,然后从InternalIpcMemoryCreate()返回到PGSharedMemoryCreate()函数,再接着在分配到的共享内存的头部放一个PGShmemHeader(结构定义见下面)结构实例并初始化其成员,使全局静态PGShmemHeader *类型变量ShmemSegHdr指到这个结构。然后调用PGReserveSemaphores()函数分配存放信号的数组需要的内存到mySemSet数组并用on_shmem_exit()函数注册ReleaseSemaphores()函数到on_shmem_exit_list数组,这个数组大小和backend进程数有关。

typedef structPGShmemHeader /*standard header for all Postgres shmem */

{

int32 magic; /* magic #to identify Postgres segments */

#define PGShmemMagic 679834894

pid_t creatorPID; /* PID ofcreating process */

Size totalsize; /* total size ofsegment */

Size freeoffset; /* offset tofirst free space */

void *index; /* pointer to ShmemIndex table */

#ifndef WIN32 /* Windows doesn't have useful inode#s */

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇PostgreSQL启动过程中的那些事七.. 下一篇bbed修改undo段状态(ORA-01578)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: