学习链接:
https://www.cnblogs.com/dasusu/p/9810673.html
问题
- Q1:你知道 so 文件的加载流程吗?
- Q2:设备存放 so 的路径有 system/lib,vendor/lib,system/lib64,vendor/lib64,知道在哪里规定了这些路径吗?清楚哪些场景下系统会去哪个目录下寻找 so 文件吗?还是说,所有的目录都会去寻找?
- Q3:Zygote 进程是分 32 位和 64 位的,那么,系统是如何决定某个应用应该运行在 32 位上,还是 64 位上?
- Q4:如果程序跑在 64 位的 Zygote 进程上时,可以使用 32 位的 so 文件么,即应用的 primaryCpuAbi 为 arm64-v8a,那么是否可使用 armeabi-v7a 的 so 文件,兼容的吗?
总结
- 一个应用在安装过程中,系统会经过一系列复杂的逻辑确定两个跟 so 文件加载相关的 app 属性值:nativeLibraryDirectories ,primaryCpuAbi ;
- nativeLibraryDirectories 表示应用自身存放 so 文件的目录地址,影响着 so 文件的加载流程;
- primaryCpuAbi 表示应用应该运行在哪种 abi 上,如(armeabi-v7a),它影响着应用是运行在 32 位还是 64 位的进程上,进而影响到寻找系统指定的 so 文件目录的流程;
- 以上两个属性,在应用安装结束后,可在 data/system/packages.xml 中查看;
- 当调用 System 的 loadLibrary() 加载 so 文件时,流程如下:
- 先到 nativeLibraryDirectories 指向的目录中寻找,是否存在且可用的 so 文件,有则直接加载这里的 so 文件;
- 上一步没找到的话,则根据当前进程如果是 32 位的,那么依次去 vendor/lib 和 system/lib 目录中寻找;
- 同样,如果当前进程是 64 位的,那么依次去 vendor/lib64 和 system/lib64 目录中寻找;
- 当前应用是运行在 32 位还是 64 位的进程上,取决于系统的 ro.zygote 属性和应用的 primaryCpuAbi 属性值,系统的 ro.zygote 可通过执行 getprop 命令查看;
- 如果 ro.zygote 属性为 zygote64_32,那么应用启动时,会先在 ro.product.cpu.abilist64 列表中寻找是否支持 primaryCpuAbi 属性,有,则该应用运行在 64 位的进程上;
- 如果上一步不支持,那么会在 ro.product.cpu.abilist32 列表中寻找是否支持 primaryCpuAbi 属性,有,则该应用运行在 32 位的进程上;
- 如果 ro.zygote 属性为 zygote32_64,则上述两个步骤互换;
- 如果应用的 primaryCpuAbi 属性为空,那么以 ro.product.cpu.abilist 列表中第一个 abi 值作为应用的 primaryCpuAbi;
- 运行在 64 位的 abi 有:arm64-v8a,mips64,x86_64
- 运行在 32 位的 abi 有:armeabi-v7a,armeabi,mips,x86
- 通常支持 arm64-v8a 的 64 位设备,都会向下兼容支持 32 位的 abi 运行;
- 但应用运行期间,不能混合着使用不同 abi 的 so 文件;
- 比如,当应用运行在 64 位进程中时,无法使用 32 位 abi 的 so 文件,同样,应用运行在 32 位进程中时,也无法使用 64 位 abi 的 so 文件;