笔记原创: 兰特 联系邮件:
epost_guo@126.com
参考资料: 1. Linux Device Drivers, Second Edition,
Alessandro 2. The Linux Kernel Module Programming Guide (v2.4.0), Peter Jay
Salzman Ori Pomerantz
/* * export.c -- export a symbol (maybe a
versioned one) (v2.1) * * Copyright (C) 2001 Alessandro Rubini and
Jonathan Corbet * Copyright (C) 2001 O'Reilly & Associates * *
The source code in this file can be freely used, adapted, * and
redistributed in source or binary form, so long as an * acknowledgment
appears in derived source files. The citation * should list that the code
comes from the book "Linux Device * Drivers" by Alessandro Rubini and
Jonathan Corbet, published * by O'Reilly & Associates. No warranty is
attached; * we cannot take responsibility for errors or fitness for
use. * */
#ifndef __KERNEL__ # define
__KERNEL__ #endif #ifndef MODULE # define MODULE #endif
/*
This stuff might go in the Makefile, but I'd better put it here
*/
#include /* retrieve the CONFIG_* macros
*/ #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS) #
define MODVERSIONS #endif
/* * Include the versioned definitions
for both kernel symbols and our * symbol, *unless* we are generating
checksums (__GENKSYMS__ * defined) */ #if defined(MODVERSIONS) &&
!defined(__GENKSYMS__) # include #
include "export.ver" /* redefine "export_function" to include CRC
*/ #endif
/* * Everything from now on is normal. The previous
stuff can be replaced * by "$(CC) -D__KERNEL__ -DMODULE -DMODVERSIONS
-DEXPORT_SYMTAB \ * -include $(INCLUDEDIR)/linux/modversions.h" if
versioning * is enabled, and the following (simpler) cmdline for
genksyms: * "$(CC) -E -DCONFIG_MODVERSIONS
-DEXPORT_SYMTAB" */
#ifndef EXPORT_SYMTAB # define EXPORT_SYMTAB
/* need this one 'cause we export symbols */ #endif
#include
#include #include
/* printk() */
#include "sysdep.h"
/* our
dumb function, with two dumb arguments */ int export_function(int a, int
b);
#ifdef __USE_OLD_SYMTAB__ static struct symbol_table
export_syms = { #include
X(export_function), #include
}; #else EXPORT_SYMBOL(export_function); #endif
int
export_init(void) { REGISTER_SYMTAB(&export_syms); return
0; }
void export_cleanup(void) { }
int
export_function(int a, int b) {return
a+b;}
module_init(export_init); module_exit(export_cleanup);
MODULE_LICENSE("GPL");
export.c主要说明了EXPORT_SYMBOL的用法,我们已经在hello2.c中分析过了. 在这个程序里关于REGISTER_SYMTAB的用法是为了兼容2.0内核的,
我们可以现不用管它.(事实上,ldd2的作者 在编写针对内核2.0和2.4兼容的驱动程序上,做了大量的工作,
头文件"sysdep.h"主要就是做这个工作的)
显示的命名初始化函数和清除函数: module_init(export_init); module_exit(export_cleanup); 这样做的好处是内核中每一个模块的初始化函数和清除函数都会有唯一的名字,给调试带来方便. 要使用module_init和module_exit之前,
程序必须包含头文件.
在这个程序里导出了函数符号export_function,
它实现一个加法运算.
我们在import.c中用这个导出的符号. 下面是import.c的代码:
/* * import.c
-- a module using a symbol from export.c * * Copyright (C) 2001
Alessandro Rubini and Jonathan Corbet * Copyright (C) 2001 O'Reilly &
Associates * * The source code in this file can be freely used,
adapted, * and redistributed in source or binary form, so long as an *
acknowledgment appears in derived source files. The citation * should list
that the code comes from the book "Linux Device * Drivers" by Alessandro
Rubini and Jonathan Corbet, published * by O'Reilly & Associates. No
warranty is attached; * we cannot take responsibility for errors or fitness
for use. * */
#ifndef __KERNEL__ # define
__KERNEL__ #endif #ifndef MODULE # define
MODULE #endif
/* * Use versioning if needed */ #include
/* retrieve the CONFIG_* macros */ #ifdef
CONFIG_MODVERSIONS # undef MODVERSIONS /* it might be defined */ #
define MODVERSIONS #endif
#ifdef MODVERSIONS # include
# include
"export.ver" #endif
#include #include
#include "sysdep.h"
extern int
export_function(int, int);
int import_init(void) { int i =
export_function(2,2); printk("import: my mate tells that 2+2 =
%i\n",i); return 0; }
void
import_cleanup(void) {}
module_init(import_init); module_exit(import_cleanup);
MODULE_LICENSE("GPL");
在import.c中,
使用了由export.o模块导出的符号export_function(int, int), 我们加载import.o模块: insmod
import.o 结果报错:import.o: unresolved symbol export_function_Rsmp_888cb211,
错误显示export_function是一个没有定义的符号. 所以这需要我们首先加载export.o, 因为这个符号在export.c中定义: sh#
insmod export.o sh# insmod import.o 用dmesg查看输出显示: import: my mate tells
that 2+2 = 4
这种技术称为模块堆叠(module stacking)技术: 一个模块的实现倚赖于其他模块的导出的符号.
在加载这个模块之前,首先加载它所倚赖的其他模块. 只有这样, 这个模块才能成功加载和使用. |