Android中的Prelink技术

1. 原理简介

(1)Prelink
  Prelink即预链接技术是利用事先链接以代替运行时链接的技术,以加快共享库的加载速度,它不仅能加快程序启动时间,还可以减少部分内存开销(它能使KDE的启动时间减少50%)。每次程序执行时,进行的链接动作都是一样的,链接相对来说开销很大,尤其是嵌入式系统。

(2)普通Linux系统的Prelink
  Redhat系统中prelink工具(/etc/cron.dialy/prelink)会修改可执行程序,把它与所需库的链接信息加入可执行程序。在程序运行时,使用glibc(glibc > 2.3.1-r2)中的ld-linux.so来进行链接。用此方式,每次更新动态库后,使用它的程序都需要重新prelink,因为新库中的符号信息,地址等很可能与原来不同了。

(3)Android的Prelink
  Android源码中有一组map文件,其中定义了需要预连接的动态库,其Prelink信息以及对应的逻辑地址(4G地址空间中位置),在动态库编译时,预处理程序apriori根据map文件中的定义,生成预链接信息重定向信息,并加入到这些二进制文件lib*.so的末尾。它主要节约了查询函数地址等工作所用的时间,动态库重定位的开销。在运行程序,动态库加载时,加载程序linker判断动态库是否为Prelink的,如果是的话,就在首次使用时将其加载到指定的内存空间,直接使用预编译信息。

2. Android上的现状

(1)prelink-linux-arm.map

这个文件在Android源码中好像自2009年之后就不存在了,最后的一个见:https://gerrit.unlegacy-android.org/plugins/gitiles/Unlegacy-Android/android_build/+/8f83fce7f1084c5dff2f8fa99d3fdff6e045726b/core/prelink-linux-arm.map

(2)LOCAL_PRELINK_MODULE

这个是Android编译时mk文件里面可以指定的,可以决定编译so时是否启用prelink,该值设置为true要生效的前提是要在prelink-link-arm.map中定义so的偏移位置,但是好像Android 4.2之后就没有这个map文件了。(引用:《Android build系统中常用的LOCAL_变量》)

(3)仅适用于系统应用开发者,原因是这种机制必须要有系统支持才行实现

适用于Android的系统开发者,用来定制系统级的动态库,加速定制的android的系统的启动及加载速度。由于嵌入式设备尤其是android设备,目前的升级比较频繁,一旦prelink过的库函数修改过了,要求所有引用该库函数的可执行文件也要被重新编译。这就要求系统开发者谨慎的修改系统代码,毕竟每次OTA升级的代价还是很大的。

(4)主要由于安全性方面的考虑,在最新版本的各个系统中都已经放弃了prelink技术:

  参考PPT内容:《Dynamic-prelink》《Dynamic-prelink yoon esa14 slides

3. 一点体会

这种prelink机制的核心原理是由Android系统Linker(或者Linux系统的prelink进程)去帮忙做地址的预先分配与计算,省去一般动态库那种动态so地址分配以及导出符号表的地址查找与计算的过程,这样一来每个so中存储的导出符号都是预先已经计算好的符号绝对地址了,而不是未决的(导出)偏移地址。从而起到提高动态库加载速度的目的。

正因为如此,必须要系统级的支持才能实现,不可能由某个应用级APP来自行控制。

原文地址:https://www.cnblogs.com/kuliuheng/p/12195960.html