pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
在你创建并注册一个用户定义的函数之后,你的工作基本上就完成了。然而, Postgres必须装载实现你的函数的目标代码 (例如一个.o文件或一个共享库)。如前所述, Postgres会在运行时按需装载你的代码。为了让你的代码能够被动态装载,你可能必须以一种特殊的方式对它进行编译和 linkedit。本节简要描述在你把用户定义的函数装载进运行中的Postgres服务器之前,需要怎样进行编译和 linkediting。注意,这一过程从 4.2 版开始已经改变。
旧的Postgres动态装载机制要求编写动态装载器的人深入了解可执行文件格式、可执行指令在内存中的放置和对齐等方面的知识。那样的装载器往往又慢又有缺陷。从 4.2 版开始, Postgres的动态装载机制已被重写为使用操作系统提供的动态装载机制。这种做法通常比我们以前的动态装载机制更快、更可靠也更可移植。原因在于,几乎所有现代版本的 UNIX 都使用动态装载机制来实现共享库,因此必然提供快速可靠的机制。另一方面,目标文件在被装载进 Postgres之前必须先做一点后处理。我们希望速度和可靠性上的大幅提升能弥补便利性上的轻微下降。
如果你有具体问题,应该预期去阅读(反复阅读)C 编译器 cc(1) 和链接编辑器 ld(1) 的手册页。此外, PGROOT/src/regress目录中的回归测试套件包含这一过程的若干可用示例。如果你照抄这些测试的做法,就不会有任何问题。 下面将使用下列术语:
动态装载(Dynamic loading)是Postgres对一个目标文件所做的事情。目标文件被复制进运行中的Postgres服务器,文件中的函数和变量变得可供Postgres进程中的函数使用。Postgres使用操作系统提供的动态装载机制来完成这件事。
装载和链接编辑(Loading and link editing)是你对一个目标文件所做的事情,目的是产生另一种目标文件(例如一个可执行程序或一个共享库)。你使用链接编辑程序 ld(1) 来完成这件事。
下列一般性限制和说明也适用于下面的讨论:
传给 create function 命令的路径必须是绝对路径(即以“/”开头),并且指向运行Postgres服务器的机器上可见的目录。
相对路径实际上也能工作,但它是相对于数据库所在目录的(前端应用通常看不到这个目录)。显然,让路径相对于用户启动前端应用的目录是没有意义的,因为服务器可能运行在一台完全不同的机器上!
Postgres用户必须能够遍历传给 create function 命令的路径,并且能够读取该目标文件。这是因为Postgres服务器以Postgres用户身份运行,而不是以启动前端进程的用户身份运行。(让文件或上层目录对“postgres”用户不可读和/或不可执行是一个极其常见的错误。)
目标文件内定义的符号名彼此不能冲突,也不能与Postgres中定义的符号冲突。
GNU C 编译器通常不提供使用操作系统动态装载器接口所需的特殊选项。在这种情况下,必须使用操作系统自带的 C 编译器。
在 ULTRIX 下构建动态装载的目标文件非常容易。ULTRIX 没有任何 sharedlibrary 机制,因此对动态装载器接口没有任何限制。另一方面,我们不得不自己(重)写一个不可移植的动态装载器,也无法使用真正的共享库。在 ULTRIX 下,唯一的限制是每个目标文件都必须用选项 -G 0 生成。(注意那是数字“0”而不是字母“O”。)例如,
# simple ULTRIX example
% cc -G 0 -c foo.c
会产生一个名为 foo.o 的目标文件,随后可以把它动态装载进Postgres。不需要再做额外的装载或链接编辑。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。