我们知道insmod使用公共内核符号表来解析模块中未定义的符号。公共内核符号表中包含了所有
的全局内核项(即函数和变量)的地址,这是实现模块化驱动程序所必需的。当模块被装入内核
后,它所导出的任何内核符号都会变成内核符号表的一部分。在通常情况下,模块只需实现自己
的功能,而无需导出任何符号。但是,如果其他模块需要从某个模块中获得好处时,我们也可以
导出符号。
新模块可以使用由我们自己的模块导出的符号,这样,我们可以在其他模块上层叠新的模块。模
块层叠技术也使用在很多主流的内核源代码中。例如msdos文件系统依赖于由fat模块导出的符号;
而每个USB输入设备模块层叠在usbcore和input模块之上。
Linux内核头文件提供了一个方便的方法来管理符号对模块外部的可见性,从而减少了可能造成
的名字空间污染(名字空间中的名称可能会和内核其他地方定义的名称发生冲突),并且适当隐
藏信息。如果一个模块需要向其他模块导出符号,则应该使用下面的宏:
EXPORT_SYMBOL(name);
EXPORT_SYMOBL_GPL(name);
这两个宏均用于将给定的符号导出到模块外部。_GPL版本使得要导出的符号只能被GPL许可证下
的模块使用。符号必须在模块文件的全局部分导出,不能再函数中导出,这是因为上面的这两个
宏将被展开为一个特殊变量的声明,而该变量必须是全局的。该变量将在模块可执行文件的特殊
部分(即一个"ELF段")中保存,在装载时,内核通过这个段来寻找模块导出的变量。