Linux 2.6的“/proc/kallsyms”文件对应着内核符号表,它记录了符号以及符号所在的内存地址。
模块可以使用如下宏导出符号到内核符号表:
EXPORT_SYMBOL(符号名);
EXPORT_SYMBOL_GPL(符号名);
Module.symvers 存储了导出符号的信息
头文件
symbol.h源码:
#ifndef __SYMBOL_HEAD_H
#define __SYMBOL_HEAD_H
struct object {
int val;
int (*func)(void);
};
#endif
测试源码:
export.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "../symbol.h"
MODULE_LICENSE("GPL");
int show(void)
{
printk("show()...");
return 0;
}
struct object obj = {
.val = 100,
.func = show,
};
EXPORT_SYMBOL_GPL(obj);
static int __init demo_init(void)
{
printk("%s,%d\n", __func__, __LINE__);
return 0;
}
static void __exit demo_exit(void)
{
printk("%s,%d\n", __func__, __LINE__);
}
module_init(demo_init);
module_exit(demo_exit);
1、先编译export.c ,生成符号表Module.symvers 拷贝到 used目录,再编译used.c
used.c源码:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "../symbol.h"
MODULE_LICENSE("GPL");
extern struct object obj;
static int __init demo_init(void)
{
printk("%s,%d\n", __func__, __LINE__);
printk("val:%d\n", obj.val);
obj.func();
return 0;
}
static void __exit demo_exit(void)
{
printk("%s,%d\n", __func__, __LINE__);
}
module_init(demo_init);
module_exit(demo_exit);
2、先加载 export.ko , 再加载 used.ko
3、先卸载 used, 再卸载 export
cat /proc/kallsyms | grep " o" // 查看符号表
相应的Makefile文件参考相关博文!