1,EXPORT_SYMBOL
EXPORT_SYMBOL( my_pub_func);
在预编译阶段会解析为:
extern void *__crc_my_pub_func __attribute__((weak));
static const unsigned long __kcrctab_my_pub_func __attribute__((__used__)) __attribute__((section("__kcrctab" ""), unused)) = (unsigned long) &__crc_my_pub_func;
static const char __kstrtab_my_pub_func[] __attribute__((section("__ksymtab_strings"))) = "" "my_pub_func";
static const struct kernel_symbol __ksymtab_my_pub_func __attribute__((__used__)) __attribute__((section("__ksymtab" ""), unused)) = { (unsigned long)&my_pub_func, __kstrtab_my_pub_func };
很显然__ksymtab_my_pub_func存储了my_pub_func的地址和符号信息,该符号对应的地址
只有insmod后才会确定;
__ksymtab_my_pub_func会链接到__ksymtab section,__ksymtab section中的所有内容就构成了
内核"导出"的符号表,这个表在insmod 时候会用到.
2,/proc/kallsyms
cat /proc/kallsyms会打印出内核当前的符号表,例如:
...
d8834a24 t snd_free_sgbuf_pages [snd_page_alloc]
c0180d7a U create_proc_entry [snd_page_alloc]
d88341d8 T snd_dma_free_pages [snd_page_alloc]
c013d858 U __get_free_pages [snd_page_alloc]
d8834ab5 t snd_malloc_sgbuf_pages [snd_page_alloc]
c014f906 U kmem_cache_alloc [snd_page_alloc]
c0106dcd U dma_alloc_coherent [snd_page_alloc]
...
其中第一列是该符号在内核地址空间中的地址;第二列是符号属性,小写表示
局部符号,大写表示全局符号,具体含义参考man nm; 第三列表示符号字符串.
3,insmod module_name.ko需要做些什么?
1),需要分配内存,将模块中包含的符号分配到内核地址空间;
2),从内核符号表解析该模块中调用的外部符号,用解析出的真实地址
代替符号地址.
4,一点启示
内核可加载模块机制和动态链接机制非常类似,但思想却非常简单.某些嵌入式
系统(比如mp3/mp4/cell phone系统)RAM空间非常有限,而且更小的SDRAM有利于
降低功耗,提高产品的竞争力,而且这类产品对外部存储的要求却不受限制(一般都
集成了大容量的nand flash,这是由产品特性所决定的).同时,这类系统需要集成
越来越多的功能,但这些功能许多时候都是独立运行,这就很适合将某些功能模
块化,在需要使用时候加载到系统内存中,不需要使用时候卸载.
受可加载模块的机制启发,很容易实现一种类似于动态链接的机制,节省系统内存.
这种机制由于思想简单,很容易在一些简单的嵌入式环境下(比如ucos,甚至没有操作
系统)实现.