ldconfig的代码中,search_dir()函数的关键内容[1]
这部分关键代码,负责查找指定目录的动态库文件,与系统已有的ld.so.cache的记录对比,如果有变化或系统缓存记录中不存在,则将当前动态库的信息加入到缓存信息链表。
继续处理,下面代码仍然是 search_dir()函数的代码,用于核对得到的缓存信息列表
的文件,把那些指向软链接的软链接文件,判断为多余的记录(节点),给予剔除。
ldconfig的帮助文档[2]说,/etc/ld.so.cache 文件的内容是有序列表,记录了/etc/ld.so.conf配置文件(及/etc/ld.so.conf.d/*.conf 这些子配置文件)中指定的目录,这些所有目录下的动态库文件的有效信息。除了这些目录,还包含了 通过命令行指定的目录、以及系统必要的目录 /lib、 /lib64 中的动态库文件信息。
从上面代码出现的hwcaps相关的处理,在此补充一下关于glibc-hwcaps的作用说明 Hackweek 20: glibc-hwcaps in openSUSE[3];glibc-hwcaps 与AMD CPU的性能优化的关系[4],指出glibc-hwcaps 是基础设施的开始,以便能够更容易地根据硬件功能交付优化的库/共享对象。这是在库级别,用于提供插入式优化库,而不是 GCC 的 FMV(函数多版本控制)之类的库,后者在构建时试图提供优化的函数,然后在运行时根据 CPU 主机进行选择。
以上代码最后看到的 add_to_cache(……),的用法是这样的:
从名称上看,就是把 找到的一个动态库的记录,添加到缓存数据结构(链表)中。这个是在for (dlib_ptr = dlibs; dlib_ptr != NULL; dlib_ptr = dlib_ptr->next) 的for 每次循环过程的最后执行的,也就是把有效的动态库信息添加到链表。
从上层看,概要的,ldconfig 生成缓存文件,有这样的大体流程:
看一看这个流程,就对ldconfig如何将最新从/etc/ld.so.conf文件读取的动态库目录下的所有动态库的缓存信息,生成为/etc/ld.so.cache缓存文件,有了整体的认识。
看完这些代码,说几点印象:
- 这些代码考虑到很多方面,不是一次成型的,通过git提交记录,以及changelog文件,我们看到Linux动态库的版本格式从glib4/5/6 有发展演化。
- glibc 的ldconfig的代码是C语言实现的,其生成的/etc/ld.so.cache缓存文件,对于Linux下的依赖动态库的可执行文件的正常运行,关系重大。所以为了优化,和确保软件更新后的稳定性,会有一套命名标准。比如SONAME的命名机制。对软链接是否有效的判断,以及对新动态库的软链接信息的更新。所以总体流程还是比较繁杂的。要考虑到的细节比较多。从git commit历史看,代码维护者的名称大部分是国外开发者。
- ldconfig 的C语言风格有编码排版约定,可读性尚可。也做了模块拆分(如 ldconfig的功能,划分到了多个文件,如入口文件 ldconfig.c 、缓存的读写逻辑实现文件 cache.c 、SONAME文件辅助功能文件readlib.c 、 chroot功能文件 chroot_canon.c )
- ldconfig 的代码存在的不足,也是很多C项目的问题,使用了很多全局变量,各个函数到处在直接操作全局变量。虽然功能上没问题,高手写的代码也不会有运行异常,但总感觉可读性和内聚程度降低了。如果是我来实现ldcnfig,我会在内聚性和代码注释方面做一些改进。减少全局静态变量的使用;改成main()内部的变量,且通过main向被调用的函数传参指针参数的方式传入待读写的变量。以此提高可读性。
- 部分函数的单函数代码行数过长,比如search_dir(),还可以再拆分成多个函数。也是为了可读性能好一些。
- 部分关键结构体的成员变量定义时,没有注释说明其作用。虽然通过看调用代码能知道,但这样的struct定义降低了可读性。
总之,通过本系列文章对Linux 的ldconfig命令的源码,从读动态缓存文件、打印库缓存信息、查找/etc/ld.so.conf 指定的目录的动态库信息等功能做了原理分析。希望对读者理解ldconfig的原理些许帮助。
参考资料:
- [1]ldconfig的代码中,search_dir()函数的关键内容: https://sourceware.org/git?p=glibc.git;a=blob;f=elf/ldconfig.c;h=bccd386761d8cbb226bd3b02c17bf55cd552cee4;hb=HEAD#l702
- [2]ldconfig的帮助文档: https://www.man7.org/linux/man-pages/man8/ldconfig.8.html
- [3]Hackweek 20: glibc-hwcaps in openSUSE: https://antlarr.io/tag/glibc-hwcaps/
- [4]glibc-hwcaps 与AMD CPU的性能优化的关系: https://www.phoronix.com/news/glibc-hwcaps-RFC