PostmasterMain()中的process table的初始化后内存结构
|||
上次写完了“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()
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的部分。
至此,结束。
Postmaster在PostmasterMain()->reset_shared()->CreateSharedMemoryAndSemaphores()中初始化process table的主要函数为:
/*
* Set up process table
*/
- InitProcGlobal();
- CreateSharedProcArray();
- CreateSharedBackendStatus();
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的部分。
至此,结束。