符号依赖
模块版本校验通过内核选项**CONFIG_MODVERSIONS **打开,这是一项简单的ABI一致性检查。它会为每个导出的符号生成一个CRC值。当一个外部模块被加载使用的时候,内核导出符号的CRC值会和模块导出符号的CRC值做比较。如果两者不匹配,内核将拒绝将该模块加载到内核中。保存导出符号信息的是名为“Module.symvers”的文件,内核编译的时候就会生成一个Module.symvers文件,其中包含所有内核和各个模块导出的符号信息。其格式如下,如果内核没有开启CONFIG_MODVERSIONS,则CRC一栏是0x00000000.
1 | <CRC> <Symbol> <module> |
当编译一个外部模块的时候,编译系统需要读取内核编译时生成的Module.symvers文件,以检查模块需要的所有外部符号是否在内核中有定义且已导出。整个过程是在MODPOST阶段做的,MODPOST从内核源码树中获取内核的Module.symvers文件。如果在模块编译目录下也有Module.symvers文件,那该文件同样会被MODPOST读取。在MODPOST期间,会生成一个新的Module.symvers文件,其包含所有未在内核中定义的符号。
有时候,外部模块之间有依赖关系。比如有两个模块,foo.ko依赖bar.ko导出的文件。内核编译系统提供三种办法来满足这个需求
使用顶层KBuild文件
将foo和bar写到一个KBuild文件中,内核会自动处理模块依赖关系。生成的Module.symvers包含两个模块导出的所有符号。
复制Module.symvers文件
根据前面描述,当编译好bar.ko的时候,可以将bar模块的Module.symvers复制到foo的模块源码目录中
使用make变量
make有一个KBUILD_EXTRA_SYMBOLS变量,用以指定在编译某个模块时所读取的外部Module.symvers文件。KBUILD_EXTRA_SYMBOLS后面跟文件列表,文件用空格分隔。