Linux从源码分析ldconfig命令对可执行文件缓存信息的读取原理(缓存文件的读)
原创Linux从源码分析ldconfig命令对可执行文件缓存信息的读取原理
ldconfig命令是Linux系统中用于维护动态链接库缓存的一个实用工具。它能够更新动态链接器使用的缓存文件,从而促使系统能够正确地找到和加载所需的动态链接库。本文将深入分析ldconfig命令的源码,探讨其对可执行文件缓存信息的读取原理。
1. 引言
在Linux系统中,动态链接库(DLL,在Linux中称为共享库)为程序提供了扩展功能,促使程序可以不重新编译就能使用新的功能。ldconfig命令的作用就是确保动态链接器(ld.so)能够找到这些共享库,并将其缓存到系统的一个文件中,以便于敏捷访问。
2. ldconfig命令的工作流程
ldconfig命令的工作流程大致如下:
- 读取配置文件,确定搜索共享库的路径。
- 遍历这些路径,查找所有的共享库文件。
- 将找到的共享库信息写入缓存文件中。
- 更新动态链接器的缓存信息。
3. 源码分析
ldconfig命令的源码位于Linux内核源码树的`tools/lib/ldconfig`目录下。下面我们将通过几个关键步骤来分析ldconfig命令的源码。
3.1. 读取配置文件
ldconfig命令首先会读取配置文件,配置文件通常位于`/etc/ld.so.conf`或`/etc/ld.so.conf.d/`目录下。以下是一个明了的配置文件示例:
# /etc/ld.so.conf
/lib
/lib64
/usr/lib
/usr/lib64
ldconfig命令会使用`read_conf`函数来读取配置文件,并填充一个路径列表。
static void read_conf(void)
{
FILE *conf;
char line[PATH_MAX];
char *path;
char *token;
int fd;
conf = fopen("/etc/ld.so.conf", "r");
if (!conf) {
fprintf(stderr, "ldconfig: %s: %s ", "/etc/ld.so.conf", strerror(errno));
return;
}
while (fgets(line, sizeof(line), conf)) {
line[strcspn(line, " ")] = '\0';
token = strtok(line, ":");
while (token) {
if (add_path(token) == -1) {
fprintf(stderr, "ldconfig: failed to add path: %s ", token);
}
token = strtok(NULL, ":");
}
}
fclose(conf);
}
3.2. 遍历路径
读取配置文件后,ldconfig命令会遍历所有路径,查找共享库文件。这个过程是通过`scan_dirs`函数完成的,该函数会对每个路径调用`scan_dir`函数。
static void scan_dirs(void)
{
char **paths;
size_t i;
paths = get_path_list();
for (i = 0; paths[i] != NULL; i++) {
scan_dir(paths[i]);
}
free_path_list(paths);
}
在`scan_dir`函数中,会遍历指定路径下的所有文件,并检查文件名是否符合共享库的命名规则。符合条件的文件会被添加到缓存列表中。
static void scan_dir(const char *dir)
{
DIR *d;
struct dirent *de;
char path[PATH_MAX];
struct stat sb;
d = opendir(dir);
if (!d) {
fprintf(stderr, "ldconfig: failed to open directory %s: %s ", dir, strerror(errno));
return;
}
while ((de = readdir(d)) != NULL) {
if (de->d_type == DT_REG) {
snprintf(path, sizeof(path), "%s/%s", dir, de->d_name);
if (is_library(path, &sb)) {
add_cache_entry(path, sb.st_mtime);
}
}
}
closedir(d);
}
3.3. 写入缓存文件
遍历完成后,ldconfig命令会将找到的共享库信息写入缓存文件`/etc/ld.so.cache`中。这个过程是通过`write_cache`函数完成的。
static void write_cache(void)
{
FILE *fp;
char *buffer;
size_t len;
struct cache_entry *entry;
size_t i;
fp = fopen