PostgreSQL shared_preload_libraries 动态库的加载逻辑分析

2023年 8月 15日 67.7k 0

PostgreSQL 支持安装扩展(extension),有些扩展的安装,需要在配置文件 postgresql.conf 中提前配置,并在 PG 主程序启动时提前加载,比如 timescaledb,如下:

shared_preload_libraries = 'timescaledb'

这类扩展实际上就是一个 .so 动态库,PG 主程序在启动时,提前将这些动态库加载到进程中。
PG 主进程 postmaster 在启动时,调用 internal_load_library() 函数,进行动态库的加载,函数调用关系如下:

main()
->PostmasterMain()
->process_shared_preload_libraries()
->load_libraries()
->load_file()
->internal_load_library()

可以看出,加载一个扩展(extenstion)的核心代码位于函数 internal_load_library() 里面,这个函数比较短,逻辑也很简单,如下:

  1. 通过循环遍历全局变量 file_list,找出当前要安装的扩展是否已安装,如果已安装,直接返回该扩展的 handle。如果没有安装,进行下一步。
  2. 检查要安装的扩展,其文件是否可以访问,不能访问则报错退出。检查是否为已安装扩展的软链接或者硬链接,如果是,则直接返回该已安装扩展的 handle。
  3. 调用 dlopen 加载动态库文件,dlopen 返回的就是一个动态库的 handle。
  4. 调用 dlsym 获取动态库里的函数 Pg_magic_func,执行该函数,获取 Pg_magic_struct 结构体数据,并与标准的 magic_data 进行对比,进行动态库兼容性测试。
  5. 调用 dlsym 获取动态库里的函数 _PG_init,如果有该函数,则执行该函数,进行动态库的初始化。
  6. 将动态库 handle 对应的结构体加入到全局 file_list 链表中。

file_list 结构如下,file_tail 指向 file_list 链表的最后一个节点。

# src/backend/utils/fmgr/dfmgr.c

typedef struct df_files
{
struct df_files *next; /* List link */
dev_t device; /* Device file is on */
#ifndef WIN32 /* ensures we never again depend on this under
* win32 */
ino_t inode; /* Inode number of file */
#endif
void *handle; /* a handle for pg_dl* functions */
char filename[FLEXIBLE_ARRAY_MEMBER]; /* Full pathname of file */
} DynamicFileList;

static DynamicFileList *file_list = NULL;
static DynamicFileList *file_tail = NULL;

注:本文涉及到源码版本为 PG 14

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论