共享库和延迟加载
缺省情况下,模块被装入时,系统装入程序同时自动装入所有模块的从属。 因为当链接模块时,在模块的装入程序部分保存模块的从属模块列表,所以发生了从属的装入。
| 模块 | 描述 |
|---|---|
| dump-H | 允许查看从属模块列表的命令。 |
| -blazy | 在AIX® 4.2.1及更高版本中,链接器选项用于链接模块,以便在首次使用模块中的函数时,只加载模块的部分依赖项。 |
使用延迟加载时,如果模块的大多数从属从未被真正使用过,就可以程序的性能。 另一方面,每个延迟加载模块的函数调用有大约 7 个指令的额外开销,且对函数的第一个调用需要装入定义模块并修改函数调用。 因此,如果在大多数从属中运行模块调用,可能不太适合使用延迟加载。
当第一次调用延迟加载模块中定义的函数时,将进行装入定义模块并查找所期望的函数的尝试。 如果找不到该模块或该函数未由该模块导出,那么缺省行为是将错误消息打印到标准错误,并以返回码 1 退出。 应用程序可以调用_lazySetErrorHandler函数并提供错误处理程序的地址,从而提供自己的错误处理程序。 调用错误处理程序需要 3 个参数:模块的名称、符号的名称,和表示错误原因的错误值。 如果错误处理程序返回,其返回值应该为所期望的函数的替代函数的地址。 如果不存在错误处理程序,_lazySetErrorHandler 的返回值为 NULL,如果存在则为上一个处理程序的地址。
使用延迟加载通常不更改程序的行为,但有一些例外。 首先,任何与模块的装入顺序有关的程序将受到影响,因为模块可能以不同的顺序被装入,而某些模块可能根本没有被装入。
其次,比较函数指针的程序在使用延迟加载时可能无法正确工作,因为单个函数可能有多个地址。 特别是如果模块 A 调用模块 B 中的函数“f”,且在链接模块 A 时指定了模块 B 的延迟加载,那么模块 A 中所计算的“f”的地址与其他模块中所计算的“f”的地址不同。 因此,在使用延迟加载时,即使两个函数指针指向同一函数,它们也可能不相等。
第三,如果用相对路径名装入了任何模块且程序更改了工作目录,那么当需要装入从属模块时可能无法找到它们。 使用延迟加载时,如要在链接时间引用从属模块,只应该使用绝对路径名。
在链接时间,启用延迟加载的决定是一个个模块作出的。 在单个程序中,可以混合将使用延迟加载和不使用延迟加载的模块混合起来。 链接单个模块时,对从属模块中的变量的引用会防止该模块被延迟加载。 如果对模块的所有引用均为对函数符号的引用,那么从属模块可被延迟加载。
延迟加载工具可被用在线程和非线程应用程序中。
延迟加载执行跟踪
提供了一个允许在发生时查看装入活动的运行时功能部件。 这是通过使用环境变量 LDLAZYDEBUG 来实现的。 该变量的值是一个十进制、八进制(以 0 开头)或十六进制(以 0x 开头)的数,它是一个或多个以下值的总和。
| 变量 | 描述 |
|---|---|
| 第 1 年 | 显示装入或查找错误。 如果没有找到所需的模块,那么显示消息并调用延迟加载的错误处理程序。 如果所需的符号在所装入的引用模块中不可用,那么在调用错误处理程序前显示消息。 |
| 2 | 将跟踪消息写到 stderr 而不是 stdout。 缺省情况下,这些消息被写到标准输出文件流中。 该值选择了标准错误流。 |
| 4 | 显示正在被装入的模块的名称。 当需要新的模块来解析函数调用时,显示所发现并装入的模块名称。 这只在第一次引用模块内的函数时出现;即一旦模块被装入,它就一直可用于随后对该模块内的函数的引用。 不需要额外的装入操作。 |
| 8 周 | 显示所调用函数的名称。 显示所需函数功能的名称,以及预期的函数所在的模块名称。 该信息在模块被装入之前显示。 |