searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

PostgreSQL源码阅读笔记——postgres主进程启动过程

2024-11-08 09:21:26
7
0

1. main

这是整个postgres进程的程序入口。

  • 首先在startup_hacks函数中初始化全局的自旋锁dummy_spinlock
  • 调用save_ps_display_args函数,使用saved_argv保存初始的argv地址,然后将argv的内容拷贝到新申请的内存中,并让argv指向新的内存。这样做是因为postgres(master)进程在创建backend进程时,为了让用户通过ps命令可以看到不同的进程信息(包含:用户名、数据库、客户端信息等),需要将这些信息填写到原始的argv处,以便ps命令能够正确显示。同时因为在填入这些信息时,会破坏argv原有的内容,而很多系统的environ是紧挨着argv的,这样有可能导致环境变量被破坏,因此这个函数里回分配一块新的内存,将environ的内容拷贝过去,然后将environ指向新内存。
  • 调用MemoryContextInit函数创建并初始化TopMemoryContextErrorContext这两个内存管理器
  • 进行locale设置
  • 检查是否root用户启动,如果是就退出
  • 单进程模式(调试用)调用PostgresMain,多进程模式调用PostmasterMain

2. PostmasterMain

这是多进程postgres(master)进程的程序入口。

  • 取进程id保存到MyProcPidPostmasterPid中,取当前时间保存到MyStartTime
  • 设置IsPostmasterEnvironmenttrue,表示是在多进程模式中
  • 创建PostmasterContext内存管理器,并换为当前内存管理器
  • 取当前进程二进制文件全路径保存到my_exec_path,取库文件全路径保存到pkglib_path,并检查库文件路径是否能正确打开
  • 设置信号处理方式:屏蔽或设置处理函数
  • 调用InitializeGUCOptions完成配置项的初始化,主要是加载默认配置项,然后从环境变量加载配置项(详见[2.1])。
  • 处理命令行启动参数,设置配置项
  • 调用SelectConfigFiles函数加载配置文件,设置数据库的主数据目录。
  • 调用checkDataDir检查主数据目录是否可访问,以及目录下的PG_VERSION文件中记录的版本号是否正确
  • 当前工作目录切换到主数据目录
  • 调用CheckDateTokenTables对两个时间日期格式的保留字表进行正确性校验
  • 调用CreateDataDirLockFile在主数据目录下创建postmaster.pid,并在里面记录下:pid、主数据目录、启动时间和监听端口等信息。然后将该文件加入到全局的链表lock_files中,这个列表中的文件在进程退出时会被清理
  • 调用ApplyLauncherRegister注册1个后台worker。这里只是指定这个worker的主入口函数、访问权限、启动时机等信息,然后加入到一个就绪列表中,等待后续合适时机再启动进程。这里注册的worker入口函数是ApplyLauncherMain。看注释应该是注册了一个负责逻辑复制的work
  • 调用process_shared_preload_libraries加载配置文件中指定(参数: shared_preload_libraries)需要加载的插件so
  • 调用InitializeMaxBackends初始化全局变量MaxBackends,表示系统信息的进程数。该值 = 客户端最大连接数 + 自动vacuum进程数 + 最大后台进程数 + 1
  • 注册atexit回调函数:CloseServerPorts。这个函数主要就是关闭监听的所有tcp端口(记录在ListenSocket数组中),回收所有的unix socket(记录在sock_paths列表中)
  • 绑定配置中指定的所有TCP监听服务地址(ip:port),并将这些监听socket放到全局的ListenSocket数组中(步骤16中注册的回调函数会释放这些socket)。同时会把监听的第一个host记录到postmaster.pid的第6行
  • 绑定配置中指定的所有unix socket目录,在这些目录下创建unix socket句柄以及对应的lock文件句柄,并将其lock文件加入到sock_paths列表中(步骤16中注册的回调函数会释放这些unix socket)。同时会把创建的第一个unix socket记录到postmaster.pid的第5行
  • 调用reset_shared函数创建共享内存和信号量。该函数直接调用CreateSharedMemoryAndSemaphores函数(详见[2.2])
  • 调用set_max_safe_fds函数计算每个backend进程最大能打开的文件句柄数,保持在全局变量:max_safe_fds
  • 调用set_stack_base设置全局变量stack_base_ptr,这个是值取该函数第1个函数局部变量的指针值,也就是set_stack_base这个函数的栈起始地址。后面可以用这个值配合检查函数的栈起始地址是否偏移过多,也就是限制调用栈的大小
  • 调用InitPostmasterDeathWatchHandle函数创建匿名管道,读写句柄保持在全局数组:postmaster_alive_fds中。postgres(master)负责写,backend进程负责监听读,用于postgres(master)在退出时通知唤醒backend进程
  • 调用CreateOptsFile函数创建$DataDir/postmaster.opts文件,并将执行本进程的命令行保存在其中
  • 调用RemovePgTempFiles函数删除$DataDir/base/pgsql_tmp$DataDir/base$DataDir/pg_tablspc下的临时文件和关系对象
  • 调用RemovePromoteSignalFiles函数删除$DataDir/promote$DataDir/fallback_promote文件,猜测这两个文件用于将从实例提升为主
  • 删除用于保存当前日志文件名的$DataDir/current_logfiles文件
  • 调用pgstat_init函数创建一个用于收发统计信息的udp端口
  • 调用load_hba函数,读取加载$DataDir/pg_hba.conf文件,初始化用于客户端连接权限控制的全局对象parsed_hba_lines列表,和用于保存这个列表的MemoryContext对象:parsed_hba_context
  • 调用load_ident函数,读取加载$DataDir/pg_ident.conf文件,初始化用于维护操作系统用户到数据库用户映射关系的全局对象parsed_ident_lines列表,和用于保存这个列表的MemoryContext对象:parsed_ident_context
  • 获取当前时间保存到全局对象:PgStartTime
  • $DataDir/postmaster.pid文件的第8行添加字符串starting,主要是为了让pg_ctl进程能正确看到该进程的运行状况
  • 调用maybe_start_bgworkers根据情况启动一些后台进程
  • 调用ServerLoop启动postgres(master)进程的主循环:通过select处理客户端请求,如果有新的连接请求,则调用BackendStartup创建子进程。此外在处理完客户端连接请求后,还会检查所有的后台进程,如果发现有异常退出的后台进程,就尝试拉起

2.1 InitializeGUCOptions

这是初始化用户配置的主函数。

  • pg_timezone_initialize函数中初始化时区
  • 调用build_guc_variables函数,将所有配置项放到一个大数组guc_variables中,并按配置项的字符串值排序
  • 循环调用InitializeOneGUCOption函数初始化guc_variables数组中的所有配置项,主要是加载默认值
  • 设置transaction_isolationtransaction_read_onlytransaction_deferrable三个配置项
  • 调用InitializeGUCOptionsFromEnvironment函数,从环境变量中获取配置值进行设置

2.2 CreateSharedMemoryAndSemaphores

这是创建共享内存和信号量的主函数。

  • 首先判断不能是backend进程,因为这种情况下,共享内存应该已经存在,只需要attach上去
  • 计算需要的信号量个数 = MaxBackends + 辅助进程数(NUM_AUXILIARY_PROCS)
  • 根据共享内存需要存储的内存,估算其大小
  • 调用PGSharedMemoryCreate创建存放PGShmemHeader的共享内存
    • 调用CreateAnonymousSegment创建匿名的共享内存,因为是匿名的,所以应该就是这个进程自己使用,有什么作用目前还没看到
      • 如果设置使用huge page,则从/proc/meminfo中获取huge page的大小,然后将共享内存的大小扩大到huge page的整数倍,然后使用MAP_HUGETLB标志位调用mmap,这样就是使用了huge page
      • 如果使用huge page失败或者设置就是不使用,则正常调用mmap
    • 将匿名的共享内存地址记录到AnonymousShmem,其大小记录到AnonymousShmemSize
    • 注册AnonymousShmemDetach函数在on_shmem_exit_list中,以便postgres(master)退出时调用munmap释放共享内存
    • 调用InternalIpcMemoryCreate创建大小为sizeof(PGShmemHeader)的共享内存
      • 调用shmget分配共享内存
      • 注册IpcMemoryDelete函数在on_shmem_exit_list中,以便进程退出时释放共享内存
      • 调用shmat绑定共享内存
      • 注册IpcMemoryDetach函数在on_shmem_exit_list中,以便进程退出时解绑内存
      • 将共享内存的keyid记录到postmaster.pid的第7行
    • 将内存映射到PGShmemHeader对象指针,进行复制,初始化如下字段:
      • creatorPID:当前的进程id
      • magic:一个固定的整数值
      • dsm_control:共享内存的id号,在postgres(master)中为0
      • device:主数据目录的dev
      • inode:主数据目录的inode
      • totalsize:匿名共享内存的大小
      • freeoffset:剩余空闲空间的偏移量,这里其值为sizeof(PGShmemHeader)
    • 将该共享内存的地址保存到UsedShmemSegAddr,将key保存到UsedShmemSegID
    • 将共享内存的内容拷贝到匿名的共享内存AnonymousShmem中,返回AnonymousShmem(这里为什么要同时有个AnonymousShmemUsedShmemSegAddr,现在还搞不清楚)
  • 调用InitShmemAccess初始化3个全局变量:
    • ShmemSegHdr:指向上面分配的AnonymousShmem,表示PGShmemHeader对象
    • ShmemBase:数值上等于ShmemSegHdr,表示起始地址
    • ShmemEnd:AnonymousShmem的结束地址
  • 调用PGReserveSemaphores从共享内存中预留信号量对象数组的空间。其实就是在ShmemBase的共享内存空闲处(ShmemSegHdr->freeoffset)预留出足够的空间,并更新ShmemSegHdr->freeoffset。同时也会初始化3个全局变量:
    • numSems:已经实际创建的信号量,这里为:0
    • maxSems:最大能创建的信号量,这里就是前面计算的结果
    • nextSemKey:下一个信号量的key,从绑定端口号计算得到,避免不同实例冲突
  • 如果是postgres(master),则调用InitShmemAllocation初始化共享内存分配机制
    • 从共享内存中分配1个全局自旋锁对象ShmemLock,并初始化。后面从共享内存中申请空间会调用ShmemAlloc(之前都是ShmemAllocUnlocked),此函数会对ShmemLock加锁
    • 从共享内存中分配1个全局的ShmemVariableCache对象,这个对象主要保存了维护OIDXID需要的一些变量
  • 调用CreateLWLocks创建LWLock数组,如果是postgres(master),要完成下面全部操作,如果是backend进程,只需要最后一步RegisterLWLockTranches
    • 首先预估需要的内存大小,然后从共享内存中分配足够的空间
    • 将全局变量MainLWLockArray指向LWLock数组起始地址
    • 调用InitializeLWLocks初始化LWLock数组
    • 调用RegisterLWLockTranches对固定的LWLock对象进行注册,主要是分配1个全局字符串数组LWLockTrancheArray,数组大小为LWLockTranchesAllocated(该数组的下标就是某类LWLock对象的TrancheID,而其字符串就是这个对象的名字,所以实际上表示LWLock对象的TrancheID到名字的映射关系)。然后注册TranchID为64以下的固定LWLock对象的名字
  • 调用InitShmemIndex在共享内存中创建1个hash表,将ShmemSegHdr->index以及全局对象ShmemIndex指向它,后续接口绝大部分内存对象都是由这个hash表来管理
  • 调用XLOGShmemInit函数初始化pg_control对象和XLOG对象
  • 调用CLOGShmemInit函数初始化CLOG相关对象
  • 调用CommitTsShmemInit函数初始化CommitTs相关对象
  • 调用SUBTRANSShmemInit函数初始化SubTrans相关对象
  • 调用MultiXactShmemInit函数初始化MultiXact相关对象
  • 调用InitBufferPool初始化共享内存池
  • 调用InitLocks初始化锁管理对象
  • 调用InitPredicateLocks初始化predicate锁管理对象
  • 调用InitProcGlobal初始化全局进程表
  • 调用CreateSharedProcArray函数初始化ProcArray相关对象
  • 调用CreateSharedBackendStatus函数初始化BackendStatusArray相关对象
  • 调用TwoPhaseShmemInit函数初始化TwoPhaseState相关对象
  • 调用BackgroundWorkerShmemInit函数初始化BackgroundWorkerData相关对象
  • 调用CreateSharedInvalidationState函数初始化shmInvalBuffer相关对象
  • 调用PMSignalShmemInit函数初始化PMSignalState相关对象
  • 调用ProcSignalShmemInit函数初始化ProcSignalSlots相关对象
  • 调用CheckpointerShmemInit函数初始化CheckpointerShmem相关对象
  • 调用AutoVacuumShmemInit函数初始化AutoVacuumShmem相关对象
  • 调用ReplicationSlotsShmemInit函数初始化ReplicationSlotCtl相关对象
  • 调用ReplicationOriginShmemInit函数初始化replication_states_ctl相关对象
  • 调用WalSndShmemInit函数初始化WalSndCtl相关对象
  • 调用WalRcvShmemInit函数初始化WalRcv相关对象
  • 调用ApplyLauncherShmemInit函数初始化LogicalRepCtx相关对象
  • 调用SnapMgrInit函数初始化oldSnapshotControl相关对象
  • 调用BTreeShmemInit函数初始化btvacinfo相关对象
  • 调用SyncScanShmemInit函数初始化scan_locations相关对象
  • 调用AsyncShmemInit函数初始化asyncQueueControlAsyncCtl相关对象
  • 调用BackendRandomShmemInit函数初始化TwoPhaseState相关对象
  • 调用dsm_postmaster_startup创建共享内存对象dsm_control,映射到文件/dev/shm/PostgreSQL.<handleID>,这个HandleID是个随机数,保存在UsedShmemSegAddr->dsm_control字段
0条评论
0 / 1000
胡****彬
3文章数
0粉丝数
胡****彬
3 文章 | 0 粉丝
原创

PostgreSQL源码阅读笔记——postgres主进程启动过程

2024-11-08 09:21:26
7
0

1. main

这是整个postgres进程的程序入口。

  • 首先在startup_hacks函数中初始化全局的自旋锁dummy_spinlock
  • 调用save_ps_display_args函数,使用saved_argv保存初始的argv地址,然后将argv的内容拷贝到新申请的内存中,并让argv指向新的内存。这样做是因为postgres(master)进程在创建backend进程时,为了让用户通过ps命令可以看到不同的进程信息(包含:用户名、数据库、客户端信息等),需要将这些信息填写到原始的argv处,以便ps命令能够正确显示。同时因为在填入这些信息时,会破坏argv原有的内容,而很多系统的environ是紧挨着argv的,这样有可能导致环境变量被破坏,因此这个函数里回分配一块新的内存,将environ的内容拷贝过去,然后将environ指向新内存。
  • 调用MemoryContextInit函数创建并初始化TopMemoryContextErrorContext这两个内存管理器
  • 进行locale设置
  • 检查是否root用户启动,如果是就退出
  • 单进程模式(调试用)调用PostgresMain,多进程模式调用PostmasterMain

2. PostmasterMain

这是多进程postgres(master)进程的程序入口。

  • 取进程id保存到MyProcPidPostmasterPid中,取当前时间保存到MyStartTime
  • 设置IsPostmasterEnvironmenttrue,表示是在多进程模式中
  • 创建PostmasterContext内存管理器,并换为当前内存管理器
  • 取当前进程二进制文件全路径保存到my_exec_path,取库文件全路径保存到pkglib_path,并检查库文件路径是否能正确打开
  • 设置信号处理方式:屏蔽或设置处理函数
  • 调用InitializeGUCOptions完成配置项的初始化,主要是加载默认配置项,然后从环境变量加载配置项(详见[2.1])。
  • 处理命令行启动参数,设置配置项
  • 调用SelectConfigFiles函数加载配置文件,设置数据库的主数据目录。
  • 调用checkDataDir检查主数据目录是否可访问,以及目录下的PG_VERSION文件中记录的版本号是否正确
  • 当前工作目录切换到主数据目录
  • 调用CheckDateTokenTables对两个时间日期格式的保留字表进行正确性校验
  • 调用CreateDataDirLockFile在主数据目录下创建postmaster.pid,并在里面记录下:pid、主数据目录、启动时间和监听端口等信息。然后将该文件加入到全局的链表lock_files中,这个列表中的文件在进程退出时会被清理
  • 调用ApplyLauncherRegister注册1个后台worker。这里只是指定这个worker的主入口函数、访问权限、启动时机等信息,然后加入到一个就绪列表中,等待后续合适时机再启动进程。这里注册的worker入口函数是ApplyLauncherMain。看注释应该是注册了一个负责逻辑复制的work
  • 调用process_shared_preload_libraries加载配置文件中指定(参数: shared_preload_libraries)需要加载的插件so
  • 调用InitializeMaxBackends初始化全局变量MaxBackends,表示系统信息的进程数。该值 = 客户端最大连接数 + 自动vacuum进程数 + 最大后台进程数 + 1
  • 注册atexit回调函数:CloseServerPorts。这个函数主要就是关闭监听的所有tcp端口(记录在ListenSocket数组中),回收所有的unix socket(记录在sock_paths列表中)
  • 绑定配置中指定的所有TCP监听服务地址(ip:port),并将这些监听socket放到全局的ListenSocket数组中(步骤16中注册的回调函数会释放这些socket)。同时会把监听的第一个host记录到postmaster.pid的第6行
  • 绑定配置中指定的所有unix socket目录,在这些目录下创建unix socket句柄以及对应的lock文件句柄,并将其lock文件加入到sock_paths列表中(步骤16中注册的回调函数会释放这些unix socket)。同时会把创建的第一个unix socket记录到postmaster.pid的第5行
  • 调用reset_shared函数创建共享内存和信号量。该函数直接调用CreateSharedMemoryAndSemaphores函数(详见[2.2])
  • 调用set_max_safe_fds函数计算每个backend进程最大能打开的文件句柄数,保持在全局变量:max_safe_fds
  • 调用set_stack_base设置全局变量stack_base_ptr,这个是值取该函数第1个函数局部变量的指针值,也就是set_stack_base这个函数的栈起始地址。后面可以用这个值配合检查函数的栈起始地址是否偏移过多,也就是限制调用栈的大小
  • 调用InitPostmasterDeathWatchHandle函数创建匿名管道,读写句柄保持在全局数组:postmaster_alive_fds中。postgres(master)负责写,backend进程负责监听读,用于postgres(master)在退出时通知唤醒backend进程
  • 调用CreateOptsFile函数创建$DataDir/postmaster.opts文件,并将执行本进程的命令行保存在其中
  • 调用RemovePgTempFiles函数删除$DataDir/base/pgsql_tmp$DataDir/base$DataDir/pg_tablspc下的临时文件和关系对象
  • 调用RemovePromoteSignalFiles函数删除$DataDir/promote$DataDir/fallback_promote文件,猜测这两个文件用于将从实例提升为主
  • 删除用于保存当前日志文件名的$DataDir/current_logfiles文件
  • 调用pgstat_init函数创建一个用于收发统计信息的udp端口
  • 调用load_hba函数,读取加载$DataDir/pg_hba.conf文件,初始化用于客户端连接权限控制的全局对象parsed_hba_lines列表,和用于保存这个列表的MemoryContext对象:parsed_hba_context
  • 调用load_ident函数,读取加载$DataDir/pg_ident.conf文件,初始化用于维护操作系统用户到数据库用户映射关系的全局对象parsed_ident_lines列表,和用于保存这个列表的MemoryContext对象:parsed_ident_context
  • 获取当前时间保存到全局对象:PgStartTime
  • $DataDir/postmaster.pid文件的第8行添加字符串starting,主要是为了让pg_ctl进程能正确看到该进程的运行状况
  • 调用maybe_start_bgworkers根据情况启动一些后台进程
  • 调用ServerLoop启动postgres(master)进程的主循环:通过select处理客户端请求,如果有新的连接请求,则调用BackendStartup创建子进程。此外在处理完客户端连接请求后,还会检查所有的后台进程,如果发现有异常退出的后台进程,就尝试拉起

2.1 InitializeGUCOptions

这是初始化用户配置的主函数。

  • pg_timezone_initialize函数中初始化时区
  • 调用build_guc_variables函数,将所有配置项放到一个大数组guc_variables中,并按配置项的字符串值排序
  • 循环调用InitializeOneGUCOption函数初始化guc_variables数组中的所有配置项,主要是加载默认值
  • 设置transaction_isolationtransaction_read_onlytransaction_deferrable三个配置项
  • 调用InitializeGUCOptionsFromEnvironment函数,从环境变量中获取配置值进行设置

2.2 CreateSharedMemoryAndSemaphores

这是创建共享内存和信号量的主函数。

  • 首先判断不能是backend进程,因为这种情况下,共享内存应该已经存在,只需要attach上去
  • 计算需要的信号量个数 = MaxBackends + 辅助进程数(NUM_AUXILIARY_PROCS)
  • 根据共享内存需要存储的内存,估算其大小
  • 调用PGSharedMemoryCreate创建存放PGShmemHeader的共享内存
    • 调用CreateAnonymousSegment创建匿名的共享内存,因为是匿名的,所以应该就是这个进程自己使用,有什么作用目前还没看到
      • 如果设置使用huge page,则从/proc/meminfo中获取huge page的大小,然后将共享内存的大小扩大到huge page的整数倍,然后使用MAP_HUGETLB标志位调用mmap,这样就是使用了huge page
      • 如果使用huge page失败或者设置就是不使用,则正常调用mmap
    • 将匿名的共享内存地址记录到AnonymousShmem,其大小记录到AnonymousShmemSize
    • 注册AnonymousShmemDetach函数在on_shmem_exit_list中,以便postgres(master)退出时调用munmap释放共享内存
    • 调用InternalIpcMemoryCreate创建大小为sizeof(PGShmemHeader)的共享内存
      • 调用shmget分配共享内存
      • 注册IpcMemoryDelete函数在on_shmem_exit_list中,以便进程退出时释放共享内存
      • 调用shmat绑定共享内存
      • 注册IpcMemoryDetach函数在on_shmem_exit_list中,以便进程退出时解绑内存
      • 将共享内存的keyid记录到postmaster.pid的第7行
    • 将内存映射到PGShmemHeader对象指针,进行复制,初始化如下字段:
      • creatorPID:当前的进程id
      • magic:一个固定的整数值
      • dsm_control:共享内存的id号,在postgres(master)中为0
      • device:主数据目录的dev
      • inode:主数据目录的inode
      • totalsize:匿名共享内存的大小
      • freeoffset:剩余空闲空间的偏移量,这里其值为sizeof(PGShmemHeader)
    • 将该共享内存的地址保存到UsedShmemSegAddr,将key保存到UsedShmemSegID
    • 将共享内存的内容拷贝到匿名的共享内存AnonymousShmem中,返回AnonymousShmem(这里为什么要同时有个AnonymousShmemUsedShmemSegAddr,现在还搞不清楚)
  • 调用InitShmemAccess初始化3个全局变量:
    • ShmemSegHdr:指向上面分配的AnonymousShmem,表示PGShmemHeader对象
    • ShmemBase:数值上等于ShmemSegHdr,表示起始地址
    • ShmemEnd:AnonymousShmem的结束地址
  • 调用PGReserveSemaphores从共享内存中预留信号量对象数组的空间。其实就是在ShmemBase的共享内存空闲处(ShmemSegHdr->freeoffset)预留出足够的空间,并更新ShmemSegHdr->freeoffset。同时也会初始化3个全局变量:
    • numSems:已经实际创建的信号量,这里为:0
    • maxSems:最大能创建的信号量,这里就是前面计算的结果
    • nextSemKey:下一个信号量的key,从绑定端口号计算得到,避免不同实例冲突
  • 如果是postgres(master),则调用InitShmemAllocation初始化共享内存分配机制
    • 从共享内存中分配1个全局自旋锁对象ShmemLock,并初始化。后面从共享内存中申请空间会调用ShmemAlloc(之前都是ShmemAllocUnlocked),此函数会对ShmemLock加锁
    • 从共享内存中分配1个全局的ShmemVariableCache对象,这个对象主要保存了维护OIDXID需要的一些变量
  • 调用CreateLWLocks创建LWLock数组,如果是postgres(master),要完成下面全部操作,如果是backend进程,只需要最后一步RegisterLWLockTranches
    • 首先预估需要的内存大小,然后从共享内存中分配足够的空间
    • 将全局变量MainLWLockArray指向LWLock数组起始地址
    • 调用InitializeLWLocks初始化LWLock数组
    • 调用RegisterLWLockTranches对固定的LWLock对象进行注册,主要是分配1个全局字符串数组LWLockTrancheArray,数组大小为LWLockTranchesAllocated(该数组的下标就是某类LWLock对象的TrancheID,而其字符串就是这个对象的名字,所以实际上表示LWLock对象的TrancheID到名字的映射关系)。然后注册TranchID为64以下的固定LWLock对象的名字
  • 调用InitShmemIndex在共享内存中创建1个hash表,将ShmemSegHdr->index以及全局对象ShmemIndex指向它,后续接口绝大部分内存对象都是由这个hash表来管理
  • 调用XLOGShmemInit函数初始化pg_control对象和XLOG对象
  • 调用CLOGShmemInit函数初始化CLOG相关对象
  • 调用CommitTsShmemInit函数初始化CommitTs相关对象
  • 调用SUBTRANSShmemInit函数初始化SubTrans相关对象
  • 调用MultiXactShmemInit函数初始化MultiXact相关对象
  • 调用InitBufferPool初始化共享内存池
  • 调用InitLocks初始化锁管理对象
  • 调用InitPredicateLocks初始化predicate锁管理对象
  • 调用InitProcGlobal初始化全局进程表
  • 调用CreateSharedProcArray函数初始化ProcArray相关对象
  • 调用CreateSharedBackendStatus函数初始化BackendStatusArray相关对象
  • 调用TwoPhaseShmemInit函数初始化TwoPhaseState相关对象
  • 调用BackgroundWorkerShmemInit函数初始化BackgroundWorkerData相关对象
  • 调用CreateSharedInvalidationState函数初始化shmInvalBuffer相关对象
  • 调用PMSignalShmemInit函数初始化PMSignalState相关对象
  • 调用ProcSignalShmemInit函数初始化ProcSignalSlots相关对象
  • 调用CheckpointerShmemInit函数初始化CheckpointerShmem相关对象
  • 调用AutoVacuumShmemInit函数初始化AutoVacuumShmem相关对象
  • 调用ReplicationSlotsShmemInit函数初始化ReplicationSlotCtl相关对象
  • 调用ReplicationOriginShmemInit函数初始化replication_states_ctl相关对象
  • 调用WalSndShmemInit函数初始化WalSndCtl相关对象
  • 调用WalRcvShmemInit函数初始化WalRcv相关对象
  • 调用ApplyLauncherShmemInit函数初始化LogicalRepCtx相关对象
  • 调用SnapMgrInit函数初始化oldSnapshotControl相关对象
  • 调用BTreeShmemInit函数初始化btvacinfo相关对象
  • 调用SyncScanShmemInit函数初始化scan_locations相关对象
  • 调用AsyncShmemInit函数初始化asyncQueueControlAsyncCtl相关对象
  • 调用BackendRandomShmemInit函数初始化TwoPhaseState相关对象
  • 调用dsm_postmaster_startup创建共享内存对象dsm_control,映射到文件/dev/shm/PostgreSQL.<handleID>,这个HandleID是个随机数,保存在UsedShmemSegAddr->dsm_control字段
文章来自个人专栏
PG内核爱好者
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0