在所有可加载的内核模块中,当给出modulename.mod.c
,除了modulename.ko
之外, modulename.ko
生成一个名为modulename.mod.c
的文件。
以下代码摘录来自.mod.c
文件,其中包含一个{number, function}
对。 这个数字的意义是什么? 这个数字是如何由编译器生成的?
static const struct modversion_info ____versions[] __used __attribute__((section("__versions"))) = { { 0xa6d8dcb5, "module_layout" }, { 0x16c2b958, "register_netdevice" }, { 0x609f1c7e, "synchronize_net" }, { 0x90a60c63, "kmem_cache_destroy" }, { 0x402b8281, "__request_module" }, { 0x844a8af7, "netdev_info" }, { 0xdfdb0ee8, "kmalloc_caches" }, { 0x12da5bb2, "__kmalloc" }, { 0x92d42843, "cfg80211_cqm_rssi_notify" }, { 0xc86289e8, "perf_tp_event" }, ... ... }
包含在所有单独的*.mod.c
文件中的__versions
部分
CRC Symbol { 0xa6d8dcb5, "module_layout" }, { 0x16c2b958, "register_netdevice" }, ... ...
是符号及其相应的CRC的列表。 这有两个主要用途:
ko
模块时模块版本检查。 模块版本控制由CONFIG_MODVERSIONS标记启用,并用作简单的ABI一致性检查。 创建导出符号的完整原型的CRC值。 当模块被加载/使用时,内核中包含的CRC值与模块中的相似值进行比较; 如果不相等,则内核拒绝加载该模块,因为它指示该模块是参照不同版本的Linux内核源而构建的。
编译成功后,所有导出符号的所有CRC的全局列表存储在Linux内核源代码目录下的modulee.symvers
文件中。 从本质上讲,这个检查可以确保从内核模块调用的任何导出符号都存在于模块所期望的相同位置(内核偏移)。
modpost工具在编译Linux内核期间生成CRC。 它由modpost脚本调用。 整个过程在Documentation / kbuild / modules.txt:438处详细解释。
modpost工具的完整源代码在Linux内核源代码中可用。 add_depends()
是负责在每个*.mod.c
文件中生成整个__versions
节的相关函数。