动态库优化——Prelink(预连接)技术(顶嵌开源)

 

Prelink Red Hat 开发者 Jakub Jelinek 所设计的工具,正如其名字所示, Prelink 利用事先链接代替运行时链接的方法来加速共享库的加载,它不仅可以加快起动速度,还可以减少部分内存开销,是各种 Linux 架构上用于减少程序加载时间、缩短系统启动时间和加快应用程序启动的很受欢迎的一个工具。

我们在上一章中详细介绍了动态链接和加载的过程,这种运行时的动态链接尤其是重定位 (relocation) 的开销对于大型系统来说是很大的。相比之下,早期 UNIX 下的 a.out 格式的老式链接方法在速度和占用内存方面有明显的优势(但不如 ELF 格式更灵活,能方便的构建动态共享库)。 Prelink 工具是试图在保持一部分灵活性的基础上,借鉴 a.out 格式在速度和占用内存方面的优点,对 ELF 文件进行一些改进。

事实上, Prelink 工具的原理主要基于这样一个事实:动态链接和加载的过程开销很大,并且在大多数的系统上 , 函数库并不会常常被更动 , 每次程序被执行时所进行的链接动作都是完全相同的,对于嵌入式系统来说尤其如此。因此,这一过程可以改在运行时之前就可以预先处理好,即花一些时间利用 Prelink 工具对动态共享库和可执行文件进行处理,修改这些二进制文件并加入相应的重定位等信息,节约了本来在程序启动时的比较耗时的查询函数地址等工作,这样可以减少程序启动的时间,同时也减少了内存的耗用。

Prelink 的这种做法当然也有代价:我们每次更新动态共享库时,相关的可执行文件都需要重新执行一遍 Prelink 才能保证有效,因为新的共享库中的符号信息、地址等很可能与原来的已经不同了。这种代价对于嵌入式系统的开发者来说可能稍微带来一些复杂度,不过好在对用户来说几乎是可以忽略的。

更多有关 Prelink 的具体做法和细节读者可以参考 Prelink 的开发者 Jakub Jelinek 的专文介绍: http://people.redhat.com/jakub/prelink/prelink.pdf

很多 Linux 的发行版上已经预装了或者已经使用了 Prelink 工具,不过我们需要专门的针对嵌入式体系,比如 ARM 的版本,这样我们需要到 Red Hat 的网站下载源代码并重新编译。下载地址是: http://people.redhat.com/jakub/prelink/

编译时主要是 configure 时设定 --host 参数,注意它是一个用于主机而不是开发板上的工具,不要用 arm-linux-gcc 编译它,如下所示:

# ./configure --prefix=/opt/tools/arm/prelink --host=arm-linux

# make

# make install

Prelink 工具的使用非常简单,对一个系统来说可能要花几分钟或者十几分钟。一般来说我们不用在命令行中直接指定 ELF 文件的方式,而是将需要 Prelink 的文件写到配置文件 /etc/prelink.conf 中,然后使用下面的命令即可:

# prelink -avmR

如果你要取消已经做了的 Prelink 也非常简单,运行:

# prelink -au

Prelink 常用的选项含义如下:
-a
对所有的文件进行 Prelink ,包括 /etc/prelink.conf 文件中指定目录下的所有程序
-m
节省虚拟定址分配,在有许多程序需要连接时使用
-f
重新强制预连接已经连接的程序,主要用于更新连接数据时使用
-R
在给库指定地址时,使用随机地址,这有利于提高系统安全以防缓冲区溢出
-u
取消已做的预连接

下面是一份 /etc/prelink.conf 文件的示例:

    # This config file contains a list of directories both with binaries

    # and libraries prelink should consider by default.

    # If a directory name is prefixed with `-l ', the directory hierarchy

    # will be walked as long as filesystem boundaries are not crossed.

    # If a directory name is prefixed with `-h ', symbolic links in a

    # directory hierarchy are followed.

    # Blacklist specification should be prefixed by -b

# and optionally also -l or -h if needed.

    -l /opt/lib

     -l /opt/bin

    -l /opt/qte/lib

其中以 ”#” 开头的行为注释,正如注释中所解释的,下面列出的文件目录分别可以有 ”-l”, “-h” ”-b” 开头, ”-l” “-h” 区分是否包括符号连接类型的目录, ”-b” 指黑名单,即应该排除出去的部分。

你可能会在 Prelink 时遇到类似这样的错误: "Cannot prelink against non-PIC shared library"    这是因为有些库没有使用 -fPIC gcc 选项编译。 PIC Postion Independent Code ,即位置无关代码,是动态链接的一项技术,也是 Prelink 的前提条件。这种问题只需要用 -fPIC 重新编译代码就可以了。

根据笔者的经验,如果你的嵌入式系统 中动态库过多过慢是系统性能的瓶颈之一,推荐你试试 Prelink 的方法。在笔者工作的平台上,它是非常行之有效的,让大多数应用的启动时间及系统启动时间都有了显著的提升。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值