来自这里
48 struct snd_card *snd_cards[SNDRV_CARDS];
49 EXPORT_SYMBOL(snd_cards);
我不知道它的意义和为什么它被使用。我试着寻找它,但不理解它的意义。
发布于 2012-03-23 09:10:01
它使动态加载的模块能够访问符号(前提是所述模块添加了extern
声明)。
不久前,有人问如何使用它。
发布于 2019-09-11 03:49:21
这是一个很好的解释。
Extern是C存储类关键字。在内核中,就像在任何其他C代码中一样,它告诉编译器它限定的变量或函数的定义是在另一个“文件”中实现的,或者更准确地说,是在翻译单元(编程)- Wikipedia中实现的。定义它的翻译单元不应该使用静态限定符。因此,符号表具有与其相对应的条目。在链接时,符号被解析为正常。关于“extern”,没有任何特定的内核。 EXPORT_SYMBOL()是Linux内核头定义的宏。它和外星没有什么共同之处。它告诉kbuild机制,所引用的符号应该是内核符号全局列表的一部分。这反过来又允许内核模块访问它们。当然,内置在内核本身中的代码(相对于模块)可以根据规则C通过外部声明访问任何非静态符号。EXPORT_SYMBOL()机制允许我们导出一个符号供可加载模块使用。有趣的是,由一个模块导出的符号可以被可能依赖它的另一个模块访问! 总之,extern并不是特定于内核的。它用于将声明限定为来自另一个翻译单元的非静态符号.EXPORT_SYMBOL()是特定于Linux内核的。它用于定义的翻译单元,使符号可供可加载模块使用。
因此,EXPORT_SYMBOL只是一种类似于extern的机制,但它只用于可加载模块之间的引用,而不是文件。
要向前移动,我们可以猜到它是由外场完成的,因为外场是C形,是基础。
这是条线索。
https://elixir.bootlin.com/linux/v4.6.7/source/include/linux/export.h#L56
#define EXPORT_SYMBOL(sym) \
__EXPORT_SYMBOL(sym, "")
/* 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 }
首先声明一个退出系统。
然后是字符串__kstrtab_##sym == VMLINUX_SYMBOL_STR(sym)。
最后一个extern结构kernel_symbol __ksymtab_##sym ={(无符号长)&sym,__ksymtab_##sym }。_kstrtab##sym记录名称字符串,& sym 记录sym的实际地址,例如函数或变量。
发布于 2015-08-18 15:11:02
不是回答本身,而是演示,从我的评论中承诺,出口的符号不需要是非静态的。以下两个模块说明了这一点:
/* mod1.c */
#include <linux/module.h>
static int mod1_exp_func(int i)
{
pr_info("%s:%d the value passed in is %d\n",
__func__, __LINE__, i);
return i;
}
EXPORT_SYMBOL(mod1_exp_func); /* export static symbol */
static int __init mod1_init(void)
{
pr_info("Initializing simple mod\n");
return 0;
}
static void __exit mod1_exit(void)
{
pr_info("This module is exiting\n");
}
module_init(mod1_init);
module_exit(mod1_exit);
MODULE_LICENSE("GPL v2");
和第二个模块
/* mod2.c */
#include <linux/module.h>
extern int mod1_exp_func(int);
static int __init mod2_init(void)
{
pr_info("Initializing mod2\n");
pr_info("Calling exported function in mod1\n");
mod1_exp_func(3);
return 0;
}
static void __exit mod2_exit(void)
{
pr_info("mod2 exiting\n");
}
module_init(mod2_init);
module_exit(mod2_exit);
MODULE_LICENSE("GPL v2");
这些测试分别在CentOS 6和CentOS 7:内核2.6.32和3.10上进行。加载mod1.ko,然后加载mod2.ko将导致将传递给mod1_exp_func()的值打印到内核日志缓冲区。
https://stackoverflow.com/questions/9836467
复制相似问题