postgres IPCソースプローブ
pg方向のデータベースで2年近く運営されていますが、最近はソース層に入って具体的な実現プロセスを探究し始めました.書くのが乱れていて、どこがどこに書いてあるのか見てみましょう.
pgのアーキテクチャはOracleと類似しており、マルチプロセスアーキテクチャであり、類似したプロセスも多く、ログプロセス、読み書きプロセス、統計プロセスなどである.では、多くのプロセス間でどのように協同作業が行われているのでしょうか.パイプ(ハーフデュプレクス、FIFO、フルデュプレクス)、メッセージキュー、信号量、共有ストレージ(メモリ、ファイル)
pgのIPCは主にオペレーティングシステムに基づいてメモリを共有するプログラミング技術を採用し、同時にこの基礎の上で以下の機能を実現した.
1.プロセスとpostermasterの通信メカニズム
2.統合管理プロセスの関連変数と関数
3.SI Messageメカニズム、すなわち無効なメッセージングメカニズムが提供されます.
4. 相関クリアの関数.
共有メモリの実装:
ipci.c POSTGRES inter-process communication initialization code.
ipci.cでは主に共有メモリの初期化の流れを説明し、合計2つの関数:それぞれ
void RequestAddinShmemSpace(Size size)
void CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
2つの変数
static MT_LOCAL Size total_addin_request = 0;
static MT_LOCAL bool addin_request_allowed = true;
RequestAddinShmemSpaceは、システムが初期化メモリにある場合に役立ち、初期化が完了すると再呼び出しは無視され、postmasterプロセス呼び出しでない場合も無視されます.コードは次のとおりです.
CreateSharedMemoryAndSemaphoresは、postmasterプロセスが最初に呼び出されたときに共有メモリの初期化を行い、割り当てられた共有メモリのサイズを最初に計算します.
DEBUG 3がオンの場合、システム起動時に現在のプリフェッチの共有メモリサイズが出力されることがわかります.walreceiver processプロセスの申請メモリサイズを計算した後、
後でRequestAddinShmemSpaceを呼び出すと無視されます.
以上から算出したsizeに基づいてメモリ空間を申請しseghdrにヘッダアドレスを割り当てる
転送されたseghdrアドレスに基づいて,割り当てられたメモリ空間の開始アドレスと終了アドレスが得られる.
サーバが保持する信号量の数と予め保持する信号量を計算し、同時に登録終了時に関数を整理し、現在は関数を整理するのはipc.cファイルで実現
システムは共有メモリのshmem indexというHashインデックステーブルを作成します.
pgのアーキテクチャはOracleと類似しており、マルチプロセスアーキテクチャであり、類似したプロセスも多く、ログプロセス、読み書きプロセス、統計プロセスなどである.では、多くのプロセス間でどのように協同作業が行われているのでしょうか.パイプ(ハーフデュプレクス、FIFO、フルデュプレクス)、メッセージキュー、信号量、共有ストレージ(メモリ、ファイル)
pgのIPCは主にオペレーティングシステムに基づいてメモリを共有するプログラミング技術を採用し、同時にこの基礎の上で以下の機能を実現した.
1.プロセスとpostermasterの通信メカニズム
2.統合管理プロセスの関連変数と関数
3.SI Messageメカニズム、すなわち無効なメッセージングメカニズムが提供されます.
4. 相関クリアの関数.
共有メモリの実装:
ipci.c POSTGRES inter-process communication initialization code.
ipci.cでは主に共有メモリの初期化の流れを説明し、合計2つの関数:それぞれ
void RequestAddinShmemSpace(Size size)
void CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
2つの変数
static MT_LOCAL Size total_addin_request = 0;
static MT_LOCAL bool addin_request_allowed = true;
RequestAddinShmemSpaceは、システムが初期化メモリにある場合に役立ち、初期化が完了すると再呼び出しは無視され、postmasterプロセス呼び出しでない場合も無視されます.コードは次のとおりです.
void
RequestAddinShmemSpace(Size size)
{
if (IsUnderPostmaster || !addin_request_allowed)
return; /* too late */
total_addin_request = add_size(total_addin_request, size);
}
CreateSharedMemoryAndSemaphoresは、postmasterプロセスが最初に呼び出されたときに共有メモリの初期化を行い、割り当てられた共有メモリのサイズを最初に計算します.
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, SysWaitTimeStatShmemSize());
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, AppReservedConnLockShmemSize());
size = add_size(size, AppReservedConnShmemSize());
/* bug#24001: Computing needs of Shared memory size */
size = add_size(size, UserReservedConnLockShmemSize());
size = add_size(size, UserReservedConnShmemSize());
size = add_size(size, BackendStatusShmemSize());
size = add_size(size, SInvalShmemSize());
size = add_size(size, FreeSpaceShmemSize());
size = add_size(size, ProcSignalShmemSize());
size = add_size(size, BgWriterShmemSize());
size = add_size(size, BTreeShmemSize());
size = add_size(size, SyncScanShmemSize());
/* #ifdef EXEC_BACKEND */
size = add_size(size, ShmemBackendArraySize());
/* #endif */
size = add_size(size, DataFileCacheSize());
size = add_size(size, FileIdCacheSize());
size = add_size(size, RSCacheShmemSize());
/* add it finally */
size = add_size(size, XLogFileCacheSize());
/* bug#10796: for sharing xlog file handle */
size = add_size(size, XLogIdCacheSize());
/* bug#11847: Share memory for audit msg */
size = add_size(size, AuditShmemSize());
size = add_size(size, WalSndShmemSize());
size = add_size(size, WalRcvShmemSize());
/* freeze the addin request size and include it */
addin_request_allowed = false;
size = add_size(size, total_addin_request);
/* might as well round it off to a multiple of a typical page size */
size = add_size(size, 8192 - (size % 8192));
size = add_size(size, MonitorQueueSize());
size = add_size(size, EventShemeSize());
size = add_size(size, PrepareLimitShmemSize());
size = add_size(size, AutoVacShmemSize());
elog(DEBUG3, "invoking IpcMemoryCreate(size=%lu)",
(unsigned long) size);
DEBUG 3がオンの場合、システム起動時に現在のプリフェッチの共有メモリサイズが出力されることがわかります.walreceiver processプロセスの申請メモリサイズを計算した後、
addin_request_allowed = false;
後でRequestAddinShmemSpaceを呼び出すと無視されます.
seghdr = PGSharedMemoryCreate(size, makePrivate, port);
以上から算出したsizeに基づいてメモリ空間を申請しseghdrにヘッダアドレスを割り当てる
InitShmemAccess(seghdr);
void
InitShmemAccess(void *seghdr)
{
PGShmemHeader *shmhdr = (PGShmemHeader *) seghdr;
ShmemSegHdr = shmhdr;
ShmemBase = (void*) shmhdr;
ShmemEnd = (char *) ShmemBase + shmhdr->totalsize;
}
転送されたseghdrアドレスに基づいて,割り当てられたメモリ空間の開始アドレスと終了アドレスが得られる.
/*
* Create semaphores
*/
numSemas = ProcGlobalSemas();
numSemas += SpinlockSemas();
numSemas += max_parallel_threads; /* bug#12162 bdml */
PGReserveSemaphores(numSemas, port);
サーバが保持する信号量の数と予め保持する信号量を計算し、同時に登録終了時に関数を整理し、現在は関数を整理するのはipc.cファイルで実現
/*
* Set up shared memory allocation mechanism
*/
if (!IsUnderPostmaster)
InitShmemAllocation();
/*
* Now initialize LWLocks, which do shared memory allocation and are
* needed for InitShmemIndex.
*/
CreateLWLocks();
/*
* Set up shmem.c index hashtable
*/
InitShmemIndex();
システムは共有メモリのshmem indexというHashインデックステーブルを作成します.
/*
* Set up xlog, clog, and buffers
* Set up xlog, clog, and buffers
*/
XLOGShmemInit();
CLOGShmemInit();
CommitTsShmemInit();
SUBTRANSShmemInit();
MultiXactShmemInit();
InitBufferPool();
/*
* Set up lock manager
*/
InitLocks();
/*
* Set up predicate lock manager
*/
InitPredicateLocks();
/*
* Set up process table
*/
if (!IsUnderPostmaster)
InitProcGlobal();
CreateSharedProcArray();
CreateSharedBackendStatus();
TwoPhaseShmemInit();
BackgroundWorkerShmemInit();
/*
* Set up shared-inval messaging
*/
CreateSharedInvalidationState();
/*
* Set up interprocess signaling mechanisms
*/
PMSignalShmemInit();
ProcSignalShmemInit();
CheckpointerShmemInit();
AutoVacuumShmemInit();
ReplicationSlotsShmemInit();
ReplicationOriginShmemInit();
WalSndShmemInit();
WalRcvShmemInit();
ApplyLauncherShmemInit();
/*
* Set up other modules that need some shared memory space
*/
SnapMgrInit();
BTreeShmemInit();
SyncScanShmemInit();
AsyncShmemInit();
BackendRandomShmemInit();
#ifdef EXEC_BACKEND
/*
* Alloc the win32 shared backend array
*/
if (!IsUnderPostmaster)
ShmemBackendArrayAllocation();
#endif
/* Initialize dynamic shared memory facilities. */
if (!IsUnderPostmaster)
dsm_postmaster_startup(shim);
/*
* Now give loadable modules a chance to set up their shmem allocations
*/
if (shmem_startup_hook)
shmem_startup_hook();
は、次にxlog、clog、buffer、lock、process table、shared invalid messages、interprocess signaling mechanisms、および初期化を割り当てる必要があるメモリ構造モジュールに対して、shmeminitを呼び出して割り当てられたshared bufferから空の間を再割り当てます.共有メモリの申請を完了し、作業を初期化します.