init启动库文件找不到问题定位和解决
内核启动流程start_kernel->arch_call_rest_init->rest_init->kernel_init启动第一个用户空间进程。
init启动时提示库文件无法找到。
说明是ld.so正常执行,但是未能在目录列表中找到依赖的库文件。问题根源在于ld.so中默认库文件搜索路径和rootfs中不匹配。
1 ld.so主要作用和库搜索路径配置
ld.so(动态链接器)的主要作用包括:
- 动态链接:在程序运行时,ld.so 负责将程序与共享库动态链接起来,而不是在编译时静态链接。
- 库搜索:根据配置文件(如 /etc/ld.so.conf 和 /etc/ld.so.conf.d/*.conf)和环境变量(如 LD_LIBRARY_PATH),ld.so 搜索并定位所需的共享库文件。
- 符号解析:ld.so 负责解析程序中的符号引用(例如函数调用和全局变量)到共享库中的相应定义。
- 加载库:当程序需要某个库时,ld.so 加载该库到内存中,并确保库的初始化代码(如构造函数)被执行。
- 依赖管理:ld.so 处理库之间的依赖关系,确保所有依赖的库都按照正确的顺序加载。
- 版本管理:支持库的符号版本,允许库的兼容性和向后兼容性。
- 性能优化:使用 /etc/ld.so.cache 缓存文件加速库的搜索和加载过程。
- 运行时链接:允许程序在不重新编译的情况下使用更新的库版本,只要新版本保持了相同的接口。
- 安全性:可以配置为限制库的搜索路径,以防止潜在的安全风险,例如库被恶意替换。
- 环境变量:考虑 LD_LIBRARY_PATH 环境变量来搜索额外的库路径,为运行时指定库位置提供灵活性。
ld.so通过以下几种主要途径获取库搜索路径:
- 默认搜索路径:ld.so 有一些默认的搜索路径,如 /lib 和 /usr/lib 等,这些路径是预设的,不需要额外配置。
- 配置文件/etc/ld.so.conf:这是主配置文件,定义了额外的库搜索路径。管理员可以在该文件中添加自定义的库路径。
- 包含的配置文件/etc/ld.so.conf.d/*.conf:/etc/ld.so.conf 文件可能包含 include 指令,用于包含 /etc/ld.so.conf.d/ 目录下的其他配置文件。这些文件可以为特定的应用程序或库定义搜索路径。
- 环境变量LD_LIBRARY_PATH:这个环境变量可以设置额外的库搜索路径。它允许用户或应用程序指定 ld.so 应该搜索的目录,这些路径在运行时被添加到默认搜索路径中。
- 编译时指定的路径:如果程序在编译时使用了-rpath选项,那么编译器会在程序的可执行文件中嵌入这些路径。ld.so 会根据这些记录的路径搜索库。
- 缓存文件 /etc/ld.so.cache:ld.so 使用这个缓存文件来加速库的搜索过程。/etc/ld.so.cache 由 ldconfig 命令生成或更新,包含了 ld.so.conf 和所有包含的配置文件中定义的库路径。
2 解决方案
2.1 kernel中设置LD_LIBRARY_PATH
修改init/main.c中的envp_init:
const char *envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", "LD_LIBRARY_PATH=/lib;/usr/lib", NULL, };
2.2 根据ld.so中默认库搜索路径建立软链接
查看编译ld.so源码,找到默认路径。没有源码可以通过vi打开库文件搜索/lib类似的字符串。
2.3 添加ld.so.conf配置
/etc/ld.so.conf是ld.so库搜索路径的入口,可以包含/etc/ld.so.conf.d/中的配置。
cat /etc/ld.so.conf include /etc/ld.so.conf.d/*.conf
通过ldconfig读取/etc/ld.so.conf生成缓存文件到/etc/ld.so.cache。
联系方式:arnoldlu@qq.com