
路径一RegisterBackgroundWorker静态注册入口bgworker.c:871-943调用方在shared_preload_libraries加载的模块的_PG_init()函数中调用调用流程RegisterBackgroundWorker(worker) [bgworker.c:871] │ ├─ 1. 检查 IsUnderPostmaster → false此时 postmaster 刚启动 ├─ 2. 检查是否在 shared_preload_libraries 加载期间 ├─ 3. SanityCheckBackgroundWorker(worker) [bgworker.c:652] ├─ 4. 拒绝 bgw_notify_pid ! 0静态注册不允许通知 ├─ 5. 检查 numworkers max_worker_processes ├─ 6. malloc RegisteredBgWorker拷贝 worker 数据 └─ 7. slist_push_head(BackgroundWorkerList, rw-rw_lnode) ← 直接加入 postmaster 私有链表后续处理PostmasterMain() [postmaster.c:1480] │ ├─ BackgroundWorkerShmemInit() [bgworker.c:158] │ └─ 遍历 BackgroundWorkerList将每个 rw 拷贝到共享内存 │ BackgroundWorkerData-slot[slotno].worker │ 并记录 rw-rw_shmem_slot slotno │ └─ maybe_start_bgworkers() [postmaster.c:5966] └─ 遍历 BackgroundWorkerList检查启动条件 └─ do_start_bgworker(rw) [postmaster.c:5768] ├─ fork_process() / bgworker_forkexec() ← fork 子进程 ├─ child: StartBackgroundWorker() [bgworker.c:741] └─ parent: 记录 rw_pid, ReportBackgroundWorkerPID()路径二RegisterDynamicBackgroundWorker动态注册入口bgworker.c:955-1048调用方普通 backend 进程如并行查询需要启动 parallel worker 时调用流程RegisterDynamicBackgroundWorker(worker, handle) [bgworker.c:956] │ ├─ 1. 检查 IsUnderPostmaster → true必须在 backend 中调用 ├─ 2. SanityCheckBackgroundWorker(worker, ERROR) ├─ 3. LWLockAcquire(BackgroundWorkerLock, LW_EXCLUSIVE) ├─ 4. 遍历 BackgroundWorkerData-slot[] 找空闲 slotin_use false ├─ 5. 将 worker 数据 memcpy 到 slot-worker ├─ 6. 设置 slot-pid InvalidPid, slot-generation ├─ 7. pg_write_barrier() → slot-in_use true ← 写内存屏障保证可见性 ├─ 8. LWLockRelease(BackgroundWorkerLock) ├─ 9. SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE) ← 通知 postmaster └─ 10. 返回 handle含 slotno generationPostmaster 侧响应ServerLoop() [postmaster.c:1888] │ ├─ 检测信号: │ CheckPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE) │ └─ BackgroundWorkerStateChange(allow_new_workers) [bgworker.c:242] │ │ │ ├─ 遍历 BackgroundWorkerData-slot[] 所有 slot │ ├─ 找到 in_usetrue 但不在 BackgroundWorkerList 中的新 slot │ ├─ 从共享内存 slot-worker 拷贝数据到新的 RegisteredBgWorker │ ├─ 验证 bgw_notify_pid 有效性 │ └─ slist_push_head(BackgroundWorkerList, rw-rw_lnode) │ └─ maybe_start_bgworkers() [postmaster.c:5966] └─ 遍历 BackgroundWorkerList └─ do_start_bgworker(rw) [postmaster.c:5768] ├─ fork_process() ├─ child: StartBackgroundWorker() [bgworker.c:741] └─ parent: rw-rw_pid worker_pidStartBackgroundWorker被调用的两个位置StartBackgroundWorker()在子进程中执行有两个调用点场景位置说明非 EXEC_BACKEND(Unix)postmaster.c:5834fork_process()返回 0 后子进程直接调用EXEC_BACKEND(Windows)postmaster.c:5083bgworker_forkexec()→postmaster_forkexec()启动新进程进程入口SubPostmasterMain()解析--forkbgworkerN参数后调用StartBackgroundWorker内部做了什么bgworker.c:741-862设置IsBackgroundWorker true设置信号处理函数根据是否带数据库连接选择不同的 handler设置sigsetjmp异常处理InitProcess()— 创建 PGPROC 结构BaseInit()— 基础初始化LookupBackgroundWorkerFunction()— 加载动态库查找入口函数entrypt(worker-bgw_main_arg)—调用用户定义的主函数proc_exit(0)— 正常退出关键区别总结维度RegisterBackgroundWorkerRegisterDynamicBackgroundWorker调用时机postmaster 启动期间 (_PG_init)系统运行期间任意 backend调用环境!IsUnderPostmasterIsUnderPostmaster注册位置直接写入 postmaster 私有链表写入共享内存 slot通知机制无需通知postmaster 启动时自然感知SendPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE)postmaster 感知BackgroundWorkerShmemInit()时顺带处理BackgroundWorkerStateChange()扫描共享内存bgw_notify_pid不支持必须是 0支持用于通知调用进程 worker 状态变化并发控制无需单进程启动阶段BackgroundWorkerLock(LWLock)最终启动✅ 都是通过maybe_start_bgworkers()→do_start_bgworker()→StartBackgroundWorker()