大家好,又见面了,我是你们的朋友全栈君。
查看符号导出结果命令:
以EXPORT_SYMBOL(export_symbol_server)为例:
$ cat /proc/kallsyms | grep export_symbol_server
一:EXPORT_SYMBOL()宏定义相关定义如下
#define ___PASTE(a, b) a##b
#define __PASTE(a, b) ___PASTE(a, b)
#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__)
#define __ADDRESSABLE(sym) \
static void * __section(".discard.addressable") __used \
__UNIQUE_ID(__PASTE(__addressable_,sym)) = (void *)&sym;
#define __KSYMTAB_ENTRY(sym, sec) \
__ADDRESSABLE(sym) \
asm(" .section \"___ksymtab" sec "+" #sym "\", \"a\" \n" \
" .balign 4 \n" \
"__ksymtab_" #sym ": \n" \
" .long " #sym "- . \n" \
" .long __kstrtab_" #sym "- . \n" \
" .long __kstrtabns_" #sym "- . \n" \
" .previous \n")
#define __CRC_SYMBOL(sym, sec)
#define ___EXPORT_SYMBOL(sym, sec, ns) \
extern typeof(sym) sym; \
extern const char __kstrtab_##sym[]; \
extern const char __kstrtabns_##sym[]; \
__CRC_SYMBOL(sym, sec); \
asm(" .section \"__ksymtab_strings\",\"aMS\",%progbits,1 \n" \
"__kstrtab_" #sym ": \n" \
" .asciz \"" #sym "\" \n" \
"__kstrtabns_" #sym ": \n" \
" .asciz \"" ns "\" \n" \
" .previous \n"); \
__KSYMTAB_ENTRY(sym, sec)
#define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns)
#define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, "")
#define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "")
#define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "_gpl")
#define EXPORT_SYMBOL_NS(sym, ns) __EXPORT_SYMBOL(sym, "", #ns)
#define EXPORT_SYMBOL_NS_GPL(sym, ns) __EXPORT_SYMBOL(sym, "_gpl", #ns)
以EXPORT_SYMBOL(export_symbol_server)宏展开为例:
(1)EXPORT_SYMBOL(export_symbol_server)展开到第二步:
#define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, “”)
(2)_EXPORT_SYMBOL(export_symbol_server, “”)展开到第三步:
#define _EXPORT_SYMBOL(sym, sec) __EXPORT_SYMBOL(sym, sec, “”)
(3)__EXPORT_SYMBOL(export_symbol_server, “”, “”)
#define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns)
(4)___EXPORT_SYMBOL(export_symbol_server, “”, “”)展开为具体的符号:
#define ___EXPORT_SYMBOL(sym, sec, ns)
extern typeof(export_symbol_server) export_symbol_server;
extern const char __kstrtab_export_symbol_server[];
extern const char __kstrtabns_export_symbol_server[];
asm(” .section \”__ksymtab_strings\”,\”aMS\”,%progbits,1 \n”
“__kstrtab_export_symbol_server: \n”
” .asciz “export_symbol_server” \n”
“__kstrtabns_export_symbol_server: \n”
” .asciz \n”
” .previous \n”);
(5)__KSYMTAB_ENTRY(export_symbol_server, “”)展开
__ADDRESSABLE(export_symbol_server) 展开
#define ___PASTE(a, b) a##b
#define __PASTE(a, b) ___PASTE(a, b)
#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__)
static void * __section(“.discard.addressable”) __used
__UNIQUE_ID(__addressable_export_symbol_server) = (void *)&export_symbol_server;__UNIQUE_ID(__addressable_export_symbol_server):
__UNIQUE_ID___addressable_export_symbol_server__LINE__(行号)
即:static void * __section(“.discard.addressable”) __used =
__UNIQUE_ID___addressable_export_symbol_server__LINE__ = (void *)&export_symbol_server;asm(” .section \”___ksymtab+export_symbol_server\”, \”a\” \n”
” .balign 4 \n”
“__ksymtab_export_symbol_server: \n”
” .long export_symbol_server – . \n”
” .long __kstrtab_export_symbol_server- . \n”
” .long __kstrtabns_export_symbol_server- . \n”
” .previous \n”)
EXPORT_SYMBOL(export_symbol_server)完全展开:
extern typeof(export_symbol_server) export_symbol_server;
extern const char __kstrtab_export_symbol_server[];
extern const char __kstrtabns_export_symbol_server[];
asm(” .section \”__ksymtab_strings\”,\”aMS\”,%progbits,1 \n”
“__kstrtab_export_symbol_server: \n”
” .asciz “export_symbol_server” \n”
“__kstrtabns_export_symbol_server: \n”
” .asciz \n”
” .previous \n”);
static void * __section(“.discard.addressable”) __used =
__UNIQUE_ID___addressable_export_symbol_server__LINE__ = (void *)&export_symbol_server;
asm(” .section \”___ksymtab+export_symbol_server\”, \”a\” \n”
” .balign 4 \n”
“__ksymtab_export_symbol_server: \n”
” .long export_symbol_server – . \n”
” .long __kstrtab_export_symbol_server- . \n”
” .long __kstrtabns_export_symbol_server- . \n”
” .previous \n”)
符号导出结果查询:
$ cat /proc/kallsyms | grep export_symbol_server
0000000000000000 r __kstrtab_export_symbol_server [export_symbol_server]
0000000000000000 r __kstrtabns_export_symbol_server [export_symbol_server]
0000000000000000 r __ksymtab_export_symbol_server [export_symbol_server]
0000000000000000 T export_symbol_server [export_symbol_server]
0000000000000000 r __func__.20199 [export_symbol_server]
0000000000000000 t export_symbol_exit [export_symbol_server]
0000000000000000 r _note_9 [export_symbol_server]
0000000000000000 r _note_8 [export_symbol_server]
0000000000000000 d __this_module [export_symbol_server]
0000000000000000 t cleanup_module [export_symbol_server]
二:EXPORT_SYMBOL的作用
EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,即使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用。
导出符号不调用,改函数所做的动作也不会被执行。
三:使用方法
1、在模块函数定义之后使用”EXPORT_SYMBOL(函数名)”来声明。
2、在调用该函数的另外一个模块中使用extern对之声明。
3、先加载定义该函数的模块,然后再加载调用该函数的模块,请注意这个先后顺序。
注意:需要添加许可证:MODULE_LICENSE(“GPL v2”), 不然编译报错
四:测试程序
// export_symbol_server.c
#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
static int export_symbol_server(void)
{
printk("EXPORT_SYMBOL In Server: %s...\n",__func__);
return 0;
}
EXPORT_SYMBOL(export_symbol_server);
static int __init export_symbol_init(void)
{
printk("EXPORT_SYMBOL Module Server Init!\n");
return 0;
}
static void __exit export_symbol_exit(void)
{
printk("EXPORT_SYMBOL Module Server Exit!\n");
}
MODULE_LICENSE("GPL v2");
module_init(export_symbol_init);
module_exit(export_symbol_exit);
// export_symbol_client.c
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/module.h>
static int call_export_symbol(void)
{
extern int export_symbol_server(void);
printk("EXPORT_SYMBOL In Client: %s...\n",__func__);
export_symbol_server();
return 0;
}
static int __init export_symbol_init(void)
{
printk("EXPORT_SYMBOL Module Client Init!\n");
call_export_symbol();
return 0;
}
static void __exit export_symbol_exit(void)
{
printk("EXPORT_SYMBOL Module Client Exit!\n");
}
MODULE_LICENSE("GPL v2");
module_init(export_symbol_init);
module_exit(export_symbol_exit);
// Makefile
obj-m += export_symbol_server.o
obj-m += export_symbol_client.o
KDIR := /home/myroot/linux/linux-5.15.7 #内核源码路径
PWD ?= $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.mod* *.order *.symvers *.ko
五:加载内核模块
$ sudo insmod export_symbol_server.ko
$ sudo insmod export_symbol_client.ko
安装完内核模块后,查看符号导出情况:以EXPORT_SYMBOL(export_symbol_server)为例:
$ cat /proc/kallsyms | grep export_symbol_server
0000000000000000 r __kstrtab_export_symbol_server [export_symbol_server]
0000000000000000 r __kstrtabns_export_symbol_server [export_symbol_server]
0000000000000000 r __ksymtab_export_symbol_server [export_symbol_server]
0000000000000000 T export_symbol_server [export_symbol_server]
0000000000000000 r __func__.20199 [export_symbol_server]
0000000000000000 t export_symbol_exit [export_symbol_server]
0000000000000000 r _note_9 [export_symbol_server]
0000000000000000 r _note_8 [export_symbol_server]
0000000000000000 d __this_module [export_symbol_server]
0000000000000000 t cleanup_module [export_symbol_server]
查看内核模块加载情况:
$ dmesg | tail -5
[ 4777.098112] EXPORT_SYMBOL Module Server Init!
[ 4788.859055] EXPORT_SYMBOL Module Client Init!
[ 4788.859058] EXPORT_SYMBOL In Client: call_export_symbol…
[ 4788.859059] EXPORT_SYMBOL In Server: export_symbol_server…
卸载内核模块:注意顺序,先卸载调用导出函数符号的模块, 在卸载导出符号模块
$ sudo rmmod export_symbol_client
$ sudo rmmod export_symbol_server
$ dmesg | tail -3
[ 4969.121642] EXPORT_SYMBOL Module Client Exit!
[ 4976.353065] EXPORT_SYMBOL Module Server Exit!
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/160336.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...