Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393033
  • 博文数量: 119
  • 博客积分: 1796
  • 博客等级: 上尉
  • 技术积分: 890
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-14 10:16
个人简介

守正

文章分类
文章存档

2013年(1)

2011年(40)

2010年(78)

分类: LINUX

2010-07-19 13:23:35

动态库优化——Prelink(预连接)技术 更新于2009-07-07 11:28:47

关键字:

动态库优化——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的专文介绍:
很多Linux的发行版上已经预装了或者已经使用了 Prelink工具,不过我们需要专门的针对嵌入式体系,比如的 版本,这样我们需要到Red Hat的网站下载源代码并重新编译。下载地址是:
编译时主要是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的方法。在笔者工作的平台上,它是非常行之有效的,让大多数应用的启动时间及系统启动时间都有了显著的提升。
阅读(749) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~