代码之家  ›  专栏  ›  技术社区  ›  ataraxis

SystemD内置“kmod”从何处获取模块别名

  •  1
  • ataraxis  · 技术社区  · 7 年前

    当插入一个支持热插拔的设备时,udev正在加载必要的驱动程序模块。这是由以下udev规则完成的

    DRIVER!="?*", ENV{MODALIAS}=="?*", RUN{builtin}="kmod load $env{MODALIAS}"
    

    因此,kmod被调用,例如 kmod load hid:b0005g0001v0000045Ep000002E0

    内置kmod的来源记录在案 here

    hid:b0005g0001v0000045Ep000002E0 只是类似模块的别名 hid_xpadneo .

    我知道在 /usr/lib/modules/$(uname -r)/modules.alias 这些别名如下所示:

    alias hid:b0005g*v0000045Ep000002E0 hid_xpadneo
    alias hid:b0005g*v0000045Ep000002FD hid_xpadneo
    

    此文件是在编译时从所有驱动程序及其模块设备表中生成的。

    不幸的是,我找不到kmod在该文件中准确读取的位置,也找不到从中获取别名信息的位置。

    因此:kmod如何知道哪个别名代表哪个模块?

    1 回复  |  直到 7 年前
        1
  •  1
  •   KamilCuk    7 年前

    systemd/udev-builtin-kmod.c :

    static int builtin_kmod_init(void) {
            ...
            kmod_load_resources(ctx);
            ...
    }
    

    kmod/libkmod.c :

    static struct _index_files {
        const char *fn;
        const char *prefix;
    } index_files[] = {
        [KMOD_INDEX_MODULES_DEP] = { .fn = "modules.dep", .prefix = "" },
        [KMOD_INDEX_MODULES_ALIAS] = { .fn = "modules.alias", .prefix = "alias " },
        [KMOD_INDEX_MODULES_SYMBOL] = { .fn = "modules.symbols", .prefix = "alias "},
        [KMOD_INDEX_MODULES_BUILTIN] = { .fn = "modules.builtin", .prefix = ""},
    };
    
    ...
    
    KMOD_EXPORT int kmod_load_resources(struct kmod_ctx *ctx)
    {
        for (i = 0; i < _KMOD_INDEX_MODULES_SIZE; i++) {
            ...
            snprintf(path, sizeof(path), "%s/%s.bin", ctx->dirname,
                                index_files[i].fn);
            ctx->indexes[i] = index_mm_open(ctx, path,
                            &ctx->indexes_stamp[i]);
            ...
        }
    }
    

    kmon/libkmod-index.c :

    struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename,
                            unsigned long long *stamp)
    {
        ...
        if ((fd = open(filename, O_RDONLY|O_CLOEXEC)) < 0) {
        ...
    }
    

    kmod 读取并索引所有可能的文件 modules.dep modules.alias modules.symbols modules.builtin 从文件中得到别名信息。

    然后在 udev-buildin-kmod.c :

    static int builtin_kmod(sd_device *dev, int argc, char *argv[], bool test) {
            ...
            for (i = 2; argv[i]; i++)
                    (void) module_load_and_warn(ctx, argv[i], false);
            ...
    }
    

    systemd/module-util.c :

    int module_load_and_warn(struct kmod_ctx *ctx, const char *module, bool verbose) {
        ...
        r = kmod_module_new_from_lookup(ctx, module, &modlist);
        if (r < 0)
                return log_full_errno(verbose ? LOG_ERR : LOG_DEBUG, r,
                                      "Failed to lookup module alias '%s': %m", module);
    
        ...
    }
    

    里面 kmod_module_new_from_lookup 查找模块别名,即通过搜索读取到kmod对象中的数据。