暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

简单分析 pg_config 程序的作用与原理

作者:文一,应急管理大学在读本科生,中国 PostgreSQL 分会实训基地秘书长,《数据库红皮书》(线上读物)译者,曾经在中国科学院,北京航空航天大学等分享过 PostgreSQL 内核学习有关的经验与材料。MOP 社区会员,IvorySQL 社区成员。

在解决实际问题中学习可以帮助我们更快地成长,本篇文章的写作启发于彭冲老师(公众号:象楚之行)的乐知乐享群中的一次交流讨论。

pg_config 程序的作用

pg_config 程序实际上是诸多源代码编译信息的一种变相存储方式,尝试运行即可知晓:

    # 输出编译 PostgreSQL 时所使用的编译器              
    pg_config --cc
    ## 输出 PostgreSQL 所对应的版本号
    pg_config --version
    ## 输出构建 PostgreSQL 时的编译选项
    pg_config --configure


    而在实践之中,PostgreSQL 的诸多开发工作,都依赖于 pg_config 所提供的这些配置信息,如我们在安装 PostgreSQL 的拓展的时候,诸多的拓展研发者都会使用一种名为 PGXS 的开发框架,其用法案例如下所示:

    (这是 PostgreSQL 文档中对于使用 pgxs 的介绍部分,他们的原理在于把 PostgreSQL 编译时附带的 pgxs.mk 文件整合进入到拓展的 makefile 中,进而使得拓展可以安装到对应的 PostgreSQL 目录之中,而谁负责提供这个 pgxs.mk 的位置信息呢?pg_config)    

    (使用 pgxs 框架的 PostgreSQL 拓展应用程序,都依赖于 pg_config --pgxs 所提供出来的反馈信息,错误的信息将会误导拓展的部署)

    pg_config 程序的实现

    pg_config 程序的源代码位于 PostgreSQL 源代码包下面的 src/bin/pg_config/pg_config.c 中,所在文件夹的整体结构如下:

      Makefile ... make 框架下用于构建 pg_config 的指导文件              
      meson.build ... meson 框架下用于构建 pg_config 的指导文件
      nls.mk ... Makefile 的辅助用文件
      pg_config.c ... pg_configC语言源代码文件
      po ... 一组翻译文件,用于帮助 pg_config 的国际化
      t ... 用于测试 pg_configPerl 脚本

      而想要完全理解 pg_config,我们就需要对前置的一些知识做一个简单的了解,参考下面的内容:

      GNU gettext 程序

      gettext 程序由自由软件基金会(即 GNU 组织),它可以帮助我们实现程序的国际化,方法在于建立如下的转换关系:

      对应到 pg_config 程序中,就是文件中随处可见的 _(字符串)(实际会被替换为 gettext 函数) 与 po 文件的对应内容,如源代码涉及打印帮助信息的 help 部分内容,参考如下:

                       
      (这里我们选择了中文环境下面所用到的 po 文件,实际源代码包中,po 文件夹包含了数十种语言的桥梁文件)

      而在实际执行过程之中,这些字符串将会经过一个转换的流程,如我们所标记出来的"Options:\n"
      ,它将会首先传递给 gettext 组件,之后根据语言环境变量,转换为对应的字符串(如我们展示的中文环境下的翻译一样)。    

      有了对于 gettext 程序的了解之后,我们解读 pg_config 程序也就变得容易,参考下面的内容。

      pg_cofig 的工作流程

      其中:

      1.info_items 充当了内部配置项名称与对外接口的桥梁,用户所指定的参数,会首先同 info_items 数组中的对外项目匹配(即 switchname),匹配后才会转换为对应的内部配置项名称(即 configname)                

      2.获取内部配置参数的 get_configdata 中的诸多参数,是在编译时确定的,一经编译就无法修订,因此如果出现配置信息与实际情况错位的时候,最好的办法就是重新编译

      3.用户所输入的每一个参数都会引发对于配置表的完全遍历,因此即使用户指定了重复的参数(如:pg_config --cc --cc),也可以得到处理

      4.因为是逐项遍历,因此在输入参数出现错误的情况,在错误参数前的正确参数信息,也会得到输出(如: pg_config --cc --oh_no --version 中,--cc 所对应的信息将会输出,遍历到 -oh_no 时,则会提报错误然后中止)

      案例分析:PGXS 配置参数数据的确立

      我们可以深入到 get_configdata 的实现中,找到PGXS有关的内容:    

                       
      (可以发现,原理在于同几个配置项目做字符串合并)

                       
                     
      (几个目录都是在编译后确定的信息)

      其它的诸多参数的原理,大同小异,因此不做过多叙述

      写在最后:引发讨论的那个问题

      2024年7月,一位乐知乐享群中的群友在使用源代码构建 repmgr 程序的时候,遇到了如下所示的问题:

        [root@p-monitor-zabbix-db02 repmgr-5.3.3]# make              
        Makefile.global:26: /data/pg/15.5/lib/pgxs/src/makefiles/pgxs.mk: No such file or directory
        Building against PostgreSQL
        make: *** No rule to make target `/data/pg/15.5/lib/pgxs/src/makefiles/pgxs.mk'. Stop.

        同时,通过 find 程序搜索 pgxs.mk,发现 make 程序提报的路径,与真实路径,存在一定的偏差。

        最后解决的方式,也非常简单,重新编译 PostgreSQL,使得 pg_config 程序的路径发生转变,即解决了问题。

        期望

        期待更多的人参与共建 PostgreSQL 内核生态,国内的材料过于稀缺了。    

        欢迎更多的数据库爱好者加入青学会,一起投稿,交流,打造活跃的技术社区,互助互惠。
        关于青学会介绍如下:《
        青学会MOP技术社区成立了!
        添加小助手微信,实名登记后加入。

        文章转载自青年数据库学习互助会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

        评论