Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1068966
  • 博文数量: 135
  • 博客积分: 10182
  • 博客等级: 上将
  • 技术积分: 1565
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-07 16:05
文章分类

全部博文(135)

文章存档

2011年(5)

2010年(20)

2009年(3)

2008年(16)

2007年(91)

分类: LINUX

2007-04-19 20:26:44

构建和运行模块快速参考

__KERNEL__,__MODULE__预处理程序符号。在编译模块化内核代码时都必须定义。可以在源文件中定义,也可以在gcc参数中定义。

 
#include 

module_init(init_function);

module_init(init_function);

2.4内核中用来标记模块的初始化和清除函数

#include 
MOD_INC_USE_COUNT;

MOD_DEC_USE_COUNT;

MOD_IN_USE;计数非0时返回真。

操作使用计数的宏。

 

/proc/modules

当前装入内核的模块列表。

 

内核符号表相关:

EXPORT_SYMTAB;

预处理程序宏,在模块需要导出符号时定义。

EXPORT_NO_SYMBOLS;

该宏指明模块不需要导出任何符号到内核。

EXPORT_SYMBOL(symbol);

EXPORT_SYMBOL_NOVERS(symbol);

用来导出单个符号到内核的宏。第二个宏导出的符号不带版本控制信息。

 

 

MODULE_PARM(variable,type);

MODULE_PARM_DESC(variable,description);

将一个模块变量定义为参数的宏,用户随后可以在装入模块时调整这个变量的值。

eg:insmod module名 variable=(type)设定值

  模块也可以从命令行获取参数。但不是通过以前你习惯的argc/argv。要传递参数给模块,首先将获取参数值的变量声明为全局变量。然后使用宏 MODULE_PARM()(在头文件linux/module.h)。运行时,insmod将给变量赋予命令行的参数,如同 ./insmod mymodule.o myvariable=5。为使代码清晰,变量的声明和宏都应该放在 模块代码的开始部分。宏MODULE_PARM()需要两个参数,变量的名字和其类型。支持的类型有" b": 比特型,"h": 短整型, "i": 整数型," l: 长整型和 "s": 字符串型,其中正数型既可为signed也可为unsigned。 字符串类型应该声明为"char *"这样insmod就可以为它们分配内存空间。你应该总是为你的变量赋初值。 这是内核编程,代码要编写的十分谨慎。举个例子:

int myint = 3;

char *mystr;

MODULE_PARM(myint, "i");

MODULE_PARM(mystr, "s");

数组同样被支持。在宏MODULE_PARM中在类型符号前面的整型值意味着一个指定了最大长度的数组。 用'-'隔开的两个数字则分别意味着最小和最大长度。下面的例子中,就声明了一个最小长度为2,最大长度为4的整形数组。

int myshortArray[4];

MODULE_PARM (myintArray, "3-9i");

将初始值设为缺省使用的IO端口或IO内存是一个不错的作法。如果这些变量有缺省值,则可以进行自动设备检测, 否则保持当前设置的值。

最后,还有这样一个宏,MODULE_PARM_DESC()被用来注解该模块可以接收的参数。该宏 两个参数:变量名和一个格式自由的对该变量的描述。

 

MODULE_AUTHOR(author);

MODULE_DESCRIPTION(description);

MODULE_SUPPORTED_DEVICE(device);

在目标文件中添加关于模块的文档信息。

 

#inculde

必须的头文件。除非定义了__NO__VERSION__,否则它被包含在中。

__NO_VERSION__

预处理程序符号。用来防止在中声明kernel_version。

 

 

#include

int printk(const char *  fmt , ...);

函数printf的内核版。

 

#include

void *kmalloc(unsigned int size , int priority);

void kfree(void *obj);

函数malloc和free的内核版,使用GFP_KERNEL作为priority参数值。

 

 

#include

int check_region(unsigned long from, unsigned long extent);

struct resource *request_region(unsigned long from, unsigned long extern, const char *name);

void release_region(unsigned ling from, unsigned long extern);

注册和释放I/O内存区域的宏。

 

__init和__exit宏

展示了内核2.2以后引入的一个新特性。注意在负责“初始化”和“清理收尾”的函数定义处的变化。宏 __init的使用会在初始化完成后丢弃该函数并收回所占内存,如果该模块被编译进内核,而不是动态加载。

宏__initdata同__init 类似,只不过对变量有效。

宏__exit将忽略“清理收尾”的函数如果该模块被编译进内核。同宏 __exit一样,对动态加载模块是无效的。这很容易理解。编译进内核的模块 是没有清理收尾工作的, 而动态加载的却需要自己完成这些工作。

这些宏在头文件linux/init.h定义,用来释放内核占用的内存。 当你在启动时看到这样的Freeing unused kernel memory: 236k freed内核输出,上面的 那些正是内核所释放的。 

 

/proc/ksyms

公共内核了符号表。

/proc/ioports

系统中安装的设备所占用的I/O端口列表。

/proc/iomen

已分配内存区域的列表。

阅读(2231) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~