10.
4.1内核版本与模块版本的兼容性
可装入模块的编写者必须意识到,可装入模块既独立于内核又依赖于内核,所谓“独立”是因为它可以独立编译,所谓依赖是指它要调用内核或其他已装入模块的函数或变量,因此,内核版本的变化直接影响着曾经编写的模块是否能被新的内核认可。
例如,mydriver.o是基于Linux
为了解决这个问题,可装入模块的开发者就决定给模块也编以内核的版本号。在上面的例子中,mydriver.o目标文件的.modinfo特殊区段就含有“
但是,Linux
办法之一,insmod有一个-f选项来强迫insmod忽略内核版本的不匹配,并把模块插入到任何版本中,但是,你仍然会得到一个版本不匹配的警告信息。
办法之二,就是将版本信息编码进符号名中,例如将版本号作为符号名的后缀。这样如果符号名相同而版本号不一致,insmod就会认为是不同的符号而不予连接。但是,内核把是否将版本信息编码进符号名中是作为一个可选项CONFIG_MODVERSIONS来提供的。如果需要版本信息,就可以在编译内核代码前的系统配置阶段选择这个可选项;如果不需要,就可以在编译模块的源代码时加上-D CONFIG_MODVERSIONS取消这个选项。
当以符号编码来编译内核或模块时,我们前面介绍的EXPORT_SYMBOL()宏定义的形式就有所不同,例如模块最常调用的内核函数register_chrdev(),其函数名的宏定义的在C中为:
#define register_chrdev register_chrdev_Rc8dc8350
把符号register_chrdev定义为register_chrdev加上一个后缀,这个后缀就是register_chrdev()函数实际源代码的校验和,只要函数的源代码改动一个字符,这个校验和也会发生变化。因此,尽管你在源代码中读到的函数名为register_chrdev,但C的预处理程序知道真正调用的是register_chrdev_Rc8dc8350。