发信人: kevintz@GZ()
整理人: qiaoqian(2001-12-31 00:01:56), 站内信件
|
标 题: [转载] <<Linux 内核模块编程指南>>(一) 发信站: 网易虚拟社区 (Wed Jun 7 18:00:22 2000), 站内信件
【 以下文字转载自 CLanguage 讨论区 】 【 原文由 我思故我不在 所发表 】 <<Linux 内核模块编程指南>>
<<Linux Kernel Module Programming Guide>>
作者:Ori Pomerantz 中译者:kevintz([email protected])
译者注:
1、LKMPG是一本免费的书,英文版的发行和修改遵从GPL version 2的许可。为了 节省时间,我只翻译了其中的大部分的大意,或者说这只是我学习中的一些中文 笔记吧,不能算是严格上的翻译,但我认为这已经足够了。本文也允许免费发布 ,但发布前请和我联系,但不要把本文用于商业目的。鉴于本人的水平,文章中 难免有错误,请大家不吝指正。
2、本文中的例子在Linux(kernel version 2.2.10)上调试通过。你用的Linux必 须支持内核模块的加载,如果不支持,请在编译内核时选上内核模块的支持或升 级你的内核到一个支持内核模块的版本。
第一章 Hello,world
1、第一个内核模块程序
相信很多学C的人从书上学的第一个程序是Hello,world。这几乎已经是一个 传统。所以我们的内核模块编程也从Hello,world开始。
一个内核模块必须至少有两个函数:当模块被插入内核时调用的init_modul e函数和模块从内核中清除时调用的cleanup_module。通常,init_module既可以 在内核中注册(register)处理某些情况的函数,也可以用它自己的代码代替某个 内核函数(通常是先做一些自己的处理,在调用原来的函数)。cleanup_module函 数应该做init_module函数相反的工作,以便模块能够被安全地卸载。
译者注:我会保留英文版的注悉,只在关键的地方用中文做注悉
例子:hello.c
/* hello.c
* Copyright (C) 1998 by Ori Pomerantz
*
* "Hello, world" - the kernel module version.
*/
/* The necessary header files */
/* Standard in kernel modules */
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
/* Initialize the module */
int init_module()
{
printk("Hello, world - this is the kernel speaking\n");
/* If we return a non zero value, it means that init_module
failed and the kernel module can't be loaded */
return 0;
}
/* Cleanup - undid whatever init_module did */
void cleanup_module()
{
printk("Short is the life of a kernel module\n");
}
/* end of hello.c*/
2、编译hello.c的Makefile文件
一个内核模块不是一个独立的可执行文件,只是一个在运行时连接入内核的 目标文件。所以他们应该用-c选项编译成目标文件。另外,所有的内核模块都必 须用某些宏定义来编译。
__KERNEL__
这个宏定义告诉头文件这些代码是用于运行内核模块,不是作为用户进程的一部 分。
MODULE
这个宏定义告诉头文件给出适当的内核模块的定义。
LINUX
技术上讲,这个宏定义并不是必需的。然而,如果你想写一个在多个操作系统上 编译的内核模块,你应该为你定义了该宏而高兴。它允许你有条件地编译操作系 统相关的部分。还有其他一些必需或不需要的宏定义,这视乎你的内核编译选项 的需要。如果你不肯定你的内核是如何编译的,你可以看一下/usr/include/lin ux/config.h文件。
__SMP__
对称多处理器的支持。当你的内核是用支持对称多处理器选项编译的时候,必须 使用该宏定义来编译你的内核模块。如果你使用对称多处理器,你还一些其他的 事情要做,这在以后会说到。
CONFIG_MODVERSIONS
如果你的内核编译选项允许了CONFIG_MODVERSIONS,你编译内核模块时要定义宏 MODVERSIONS,而且要包含/usr/include/linux/modversions.h头文件。这些可以 在你的代码中做。
Makefile例子
# Makefile for a basic kernel module
CC=gcc
MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX
hello.o: hello.c /usr/include/linux/version.h
$(CC) $(MODCFLAGS) -c hello.c
#end of Makefile
现在剩下来的唯一事情就是su到root用户(一般你都不用root用户来执行编译 的,是吧?),然后执行insmod hello来加载hello模块,rmmod hello来卸载内核 中的hello模块。当你执行这些命令时,注意/proc/modules前后的变化。
注意:用printk打印的内核信息是输出到控制台的,当你不用X界面时,它输 出到你所使用的虚拟终端(通过Alt-F<n>选定的),你可以看到这些信息。当你用 X图形界面时,有两种可能性。一种是你用xterm -C运行一个终端,信息的输出将 送到那里显示,否则,就是另外一种情况:信息被送到虚拟终端7,将会被X窗口 所掩盖,你将看不到printk所显示的信息。
如果你的内核变得不稳定,你不应该使用X界面来得到调试信息。不用X时, 信息直接从内核到控制台。在X里面,printk打印的信息输出到用户进程xterm - C,当该进程取得CPU运行时间时,它将信息传给X的服务器进程。然后当X服务器进 程取得CPU运行时间,信息才显示出来。但一个不稳定的内核通常意味着系统将会 崩溃或重启,所以你不想延迟错误信息的输出的话,建议你使用控制台来调试内 核模块。
译者注:这个简单的例子可以直接在命令行上编译:
cc -D__KERNEL__ -DLINUX -DMODULE -c hello.c
-- 那一刹那,我开始用心去看这个世界,所有的事物真的可以看得前
所未有的那么清楚……
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.105.73.211] -- ※ 转载:.月光软件站 http://www.moon-soft.com.[FROM: 202.105.73.211]
|
|