uclinux-2008r1(bf561)内核中的EXPORT_SYMBOL

来源:互联网 发布:电杆定位仪器软件 编辑:程序博客网 时间:2024/05/29 15:17
 
   
在uclinux内核中,随处可见EXPORT_SYMBOL的定义,它的作用在于为动态插入内核的模块提供一个符号表,使之能调用内核中的函数。因而,如果内核不需要支持insmod,那么自然也就不需要EXPORT_SYMBOL。实际上,在内核没有定义CONFIG_MODULES这个宏的时候,EXPORT_SYMBOL这个宏定义什么也不做:
#define EXPORT_SYMBOL(sym)
而当需要支持insmod的时候,这个宏的定义就变成了:
#define MODULE_SYMBOL_PREFIX ""
#define __CRC_SYMBOL(sym, sec)
/* For every exported symbol, place a struct in the __ksymtab section */
#define __EXPORT_SYMBOL(sym, sec)                  /
     extern typeof(sym) sym;                   /
     __CRC_SYMBOL(sym, sec)                    /
     static const char __kstrtab_##sym[]            /
     __attribute__((section("__ksymtab_strings")))      /
     = MODULE_SYMBOL_PREFIX #sym;                      /
     static const struct kernel_symbol __ksymtab_##sym /
     __attribute_used__                   /
     __attribute__((section("__ksymtab" sec), unused)) /
     = { (unsigned long)&sym, __kstrtab_##sym }
 
#define EXPORT_SYMBOL(sym)                     /
     __EXPORT_SYMBOL(sym, "")
下面以一个实际的EXPORT_SYMBOL来分析一下这个宏的作用。在mm/nommu.c的开头有这样的语句:
struct page *mem_map;
EXPORT_SYMBOL(mem_map);
代入EXPORT_SYMBOL宏之后就变成了:
     extern struct page * mem_map;                     
     static const char __kstrtab_mem_map[]         
     __attribute__((section("__ksymtab_strings")))     
     = mem_map;                   
     static const struct kernel_symbol __ksymtab_mem_map
     __attribute_used__                  
     __attribute__((section("__ksymtab" sec), unused)) 
     = { (unsigned long)&mem_map, __kstrtab_mem_map }
在这里kernel_symbol定义为:
struct kernel_symbol
{
     unsigned long value;
     const char *name;
};
很明显,在这里定义了两个全局变量__kstrtab_mem_map__ksymtab_mem_map,值得注意的是这两个变量都是放在特定的section中的,据此猜测insmod在读取模块文件后,必须根据此模块的符号表中的名称在__ksymtab这个段中按顺序查找符号,再将此符号相对应的value替换掉动态模块中的指针(当然,目前还不理解insmod是如何取得这个段的首地址的)。
在vmlinux.lds.s中为这两个段留了空间:
     __ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {      /
         VMLINUX_SYMBOL(__start___ksymtab) = .;             /
         *(__ksymtab)                         /
         VMLINUX_SYMBOL(__stop___ksymtab) = .;          /
     }                                    /
     /* Kernel symbol table: strings */                 /
        __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) {    /
         *(__ksymtab_strings)                      /
     }                                    /
以上两个定义出现在RO_DATA的宏定义中,在vmlinux.lds.s中使用了此宏定义。
原创粉丝点击