postgres中重要的数据结构(五)

PostmasterMain()中的process table的初始化后内存结构

已有 620 次阅读 2010-4-8 05:51 |个人分类:postgresql|系统分类:科研笔记|关键词:postmaster,process table,InitProcGloble

上次写完了“Postmaster的Memory Context 初始化内存结构” http://www.sciencenet.cn/m/user_content.aspx?id=308964,接下来我们看看初始化process table 部分。
Postmaster在PostmasterMain()->reset_shared()->CreateSharedMemoryAndSemaphores()中初始化process table的主要函数为:
/*
* Set up process table
*/
  1. InitProcGlobal();
  2. CreateSharedProcArray();
  3. CreateSharedBackendStatus();
我们可以猜想一下,对于接下来PostmasterMain马上要fork的postgres的进程中肯定是用到这些函数初始化的数据结构的。我们来一一分析一下。

1.InitProcGlobal()
void InitProcGlobal(void)
{
PGPROC *procs;
int i;
bool found;

/* Create the ProcGlobal shared structure */
ProcGlobal = (PROC_HDR *)
ShmemInitStruct("Proc Header",sizeof(PROC_HDR),&found);
Assert(!found);

/*
* Create the PGPROC structures for auxiliary (bgwriter) processes,too.
* These do not get linked into the freeProcs list.
*/
AuxiliaryProcs = (PGPROC *)
ShmemInitStruct("AuxiliaryProcs",NUM_AUXILIARY_PROCS * sizeof(PGPROC),
&found);
Assert(!found);

/*
* Initialize the data structures.
*/
ProcGlobal->freeProcs = NULL;
ProcGlobal->autovacFreeProcs = NULL;

ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY;

/*
* Pre-create the PGPROC structures and create a semaphore for each.
*/
procs = (PGPROC *) ShmemAlloc((MaxConnections) * sizeof(PGPROC));
if (!procs)
ereport(FATAL,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of shared memory")));
MemSet(procs,MaxConnections * sizeof(PGPROC));
for (i = 0; i < MaxConnections; i++)
{
PGSemaphoreCreate(&(procs[i].sem));
procs[i].links.next = (SHM_QUEUE *) ProcGlobal->freeProcs;
ProcGlobal->freeProcs = &procs[i];
}

procs = (PGPROC *) ShmemAlloc((autovacuum_max_workers) * sizeof(PGPROC));
if (!procs)
ereport(FATAL,autovacuum_max_workers * sizeof(PGPROC));
for (i = 0; i < autovacuum_max_workers; i++)
{
PGSemaphoreCreate(&(procs[i].sem));
procs[i].links.next = (SHM_QUEUE *) ProcGlobal->autovacFreeProcs;
ProcGlobal->autovacFreeProcs = &procs[i];
}

MemSet(AuxiliaryProcs,NUM_AUXILIARY_PROCS * sizeof(PGPROC));
for (i = 0; i < NUM_AUXILIARY_PROCS; i++)
{
AuxiliaryProcs[i].pid = 0; /* marks auxiliary proc as not in use */
PGSemaphoreCreate(&(AuxiliaryProcs[i].sem));
}

/* Create ProcStructLock spinlock,too */
ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
SpinLockInit(ProcStructLock);
}
纵观其中的代码ProcGlobal->freeProcs = &procs[i]; 是我们比较感兴趣的。因为其他的初始化例如autovacuum类似的辅助进程我们暂时还不怎么关注。初始化的结果就是把这些结构用next指针给链接起来,本身不复杂。

2.CreateSharedProcArray()
void CreateSharedProcArray(void){
bool found;

/* Create or attach to the ProcArray shared structure */
procArray = (ProcArrayStruct *)
ShmemInitStruct("Proc Array",ProcArrayShmemSize(),&found);

if (!found)
{
/*
* We're the first - initialize.
*/
procArray->numProcs = 0;
procArray->maxProcs = MaxBackends + max_prepared_xacts;
}
}
比较关键的代码已用红色标出,注意procArray的定义:
typedef struct ProcArrayStruct
{
int numProcs; /* number of valid procs entries */
int maxProcs; /* allocated size of procs array */

/*
* We declare procs[] as 1 entry because C wants a fixed-size array,but
* actually it is maxProcs entries long.
*/
PGPROC *procs[1]; /* VARIABLE LENGTH ARRAY */
} ProcArrayStruct;

static ProcArrayStruct *procArray;
很简单,无需解释。

3.CreateSharedBackendStatus()
void CreateSharedBackendStatus(void){
Size size;
bool found;
int i;
char *buffer;

/* Create or attach to the shared array */
size = mul_size(sizeof(PgBackendStatus),MaxBackends);
BackendStatusArray = (PgBackendStatus *)
ShmemInitStruct("Backend Status Array",size,&found);

if (!found)
{
/*
* We're the first - initialize.
*/
MemSet(BackendStatusArray,size);
}

/* Create or attach to the shared activity buffer */
size = mul_size(pgstat_track_activity_query_size,MaxBackends);
BackendActivityBuffer = (char *)
ShmemInitStruct("Backend Activity Buffer",&found);

if (!found)
{
MemSet(BackendActivityBuffer,size);

/* Initialize st_activity pointers. */
buffer = BackendActivityBuffer;
for (i = 0; i < MaxBackends; i++)
{
BackendStatusArray[i].st_activity = buffer;
buffer += pgstat_track_activity_query_size;
}
}
}
主要初始化了 BackendStatusArray和 BackendActivityBuffer,并让 BackendStatusArray各项指向 BackendActivityBuffer中的各项。

这样,我们分析结束了,结论就是其实这一部分的初始化,基本上没有设定具体数据结构的值,只是把大体框架给列在那里了。
最后,我给出初始化之后在内存中的表示,图有点大的吓人,不过你可以略去shared buffer和shared memory的部分。

至此,结束。

相关文章

来源:http://www.postgres.cn/docs/11/ 4.1.1.&#160;标识符和关键词 SQL标识符和关键词必须以一个...
来源:http://www.postgres.cn/docs/11/ 8.1.&#160;数字类型 数字类型由2、4或8字节的整数以及4或8...
来源:http://www.postgres.cn/docs/11/ 5.1.&#160;表基础 SQL并不保证表中行的顺序。当一个表被读...
来源:http://www.postgres.cn/docs/11/ 6.4.&#160;从修改的行中返回数据 有时在修改行的操作过程中...
来源:http://www.postgres.cn/docs/11/ 13.2.1.&#160;读已提交隔离级别 读已提交是PostgreSQL中的...
来源:http://www.postgres.cn/docs/11/ 9.7.&#160;模式匹配 PostgreSQL提供了三种独立的实现模式匹...