Linux入门(一) -- EXPORT_SYMBOL小结

EXPORT_SYMBOL能够将函数以符号的形式导出给其他模块使用。当使用EXPORT_SYMBOL导出函数之后,我们可以在/proc/kallsyms中查到导出的函数,其显示格式如下:

[root@cosysn ~]# tail /proc/kallsyms 
ffffffffa000a720 T dm_io        [dm_mod]
ffffffffa0005860 T dm_get_device        [dm_mod]
ffffffffa00006d0 t dm_set_mdptr [dm_mod]
ffffffffa0004360 t dm_table_any_busy_target     [dm_mod]
ffffffffa0003e20 t dm_table_get_immutable_target_type   [dm_mod]
ffffffffa00007a0 t dm_suspended_md      [dm_mod]
ffffffffa00042a0 t dm_table_postsuspend_targets [dm_mod]
ffffffffa0006570 t dm_target_iterate    [dm_mod]
ffffffffa00044b0 T dm_consume_args      [dm_mod]
ffffffffa0007630 t dm_copy_name_and_uuid        [dm_mod]

对于EXPORT_SYMBOL如何实现符号导出的,下面做下简要的分析。

EXPORT_SYMBOL宏是定义在include/linux/export.h的头文件中,其定义如下:

/* 
 * 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"), aligned(1)))  \
        = VMLINUX_SYMBOL_STR(sym);                  \
        extern const struct kernel_symbol __ksymtab_##sym;\
        __visible const struct kernel_symbol __ksymtab_##sym        \
        __used                                                        \
        __attribute__((section("___ksymtab" sec "+" #sym), unused))        \
        = { (unsigned long)&sym, __kstrtab_##sym }

#define EXPORT_SYMBOL(sym)               \
        __EXPORT_SYMBOL(sym, "")

#define EXPORT_SYMBOL_GPL(sym)          \
        __EXPORT_SYMBOL(sym, "_gpl")

#define EXPORT_SYMBOL_GPL_FUTURE(sym)   \
        __EXPORT_SYMBOL(sym, "_gpl_future")

下面举例说明EXPORT_SYMBOL的作用:
如果需要将transport_lookup_cmd_lun导出为内核符号,可以调用EXPORT_SYMBOL(transport_lookup_cmd_lun);
1. 将其展开得到__EXPORT_SYMBOL(transport_lookup_cmd_lun, “”)
2. 将__EXPORT_SYMBOL展开,得到

  extern typeof(transport_lookup_cmd_lun) transport_lookup_cmd_lun;                                        \
        __CRC_SYMBOL(transport_lookup_cmd_lun, sec)                                        \
        static const char __kstrtab_transport_lookup_cmd_lun[]                        \
        __attribute__((section("__ksymtab_strings"), aligned(1))) \
        = VMLINUX_SYMBOL_STR(transport_lookup_cmd_lun);                                \
        extern const struct kernel_symbol __ksymtab_transport_lookup_cmd_lun;        \
        __visible const struct kernel_symbol __ksymtab_transport_lookup_cmd_lun        \
        __used                                                        \
        __attribute__((section("___ksymtab" sec "+" transport_lookup_cmd_lun), unused))        \
        = { (unsigned long)&transport_lookup_cmd_lun, __kstrtab_transport_lookup_cmd_lun }

下面我们对展开的宏进行分析:

static const char __kstrtab_transport_lookup_cmd_lun[]                        \
        __attribute__((section("__ksymtab_strings"), aligned(1))) \
        = VMLINUX_SYMBOL_STR(transport_lookup_cmd_lun);

该段代码表示其定义了一个名为__kstrtab_transport_lookup_cmd_lun的字符数组,并将其放到__ksymtab_strings的section下;

extern const struct kernel_symbol __ksymtab_transport_lookup_cmd_lun;        \
        __visible const struct kernel_symbol __ksymtab_transport_lookup_cmd_lun        \
        __used                                                        \
        __attribute__((section("___ksymtab" sec "+" transport_lookup_cmd_lun), unused))        \
        = { (unsigned long)&transport_lookup_cmd_lun, __kstrtab_transport_lookup_cmd_lun }

上段代码中出现了一个新的数据结构kernel_symbol,其表示内核符号

struct kernel_symbol
{
        unsigned long value; // 该内核符号的地址
        const char *name; // 该内核符号的名字
};

那么上段代码就很好理解了,其定义了一个名字为__ksymtab_transport_lookup_cmd_lun的内核符号结构用来存放符号transport_lookup_cmd_lun的地址和名字,
并将该__ksymtab_transport_lookup_cmd_lun放到___ksymtab的section下。

总结:
在内核符号导出中,调用了EXPORT_SYMBOL(sym),则会完成以下操作:
(1) 定义一个字符数组存放内核导出符号的名称,并放置到“__ksymtab_strings”的section中。
(2) 定义一个内核符号结构用于存放导出符号的内存地址和名称,并放置到”__ksymatab”中。

即通过EXPORT_SYMBOL(sym)告诉了内核以外的世界关于这个符号的两点信息:内核符号的名称和其内存地址。


[1]: 谈EXPORT_SYMBOL使用 http://blog.csdn.net/macrossdzh/article/details/4601648
[2]: 关于EXPORT_SYMBOL http://blog.csdn.net/lisan04/article/details/4076013

你可能感兴趣的:(Linux入门)