郑州市城市发展规划:为FreeBSD编写内核模块
来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 06:48:06
FreeBSD 7.0已经释出。如果你是个真正的黑客的话,投入并学习它的最好途径便是编写一个入门级的内核模块了。本文中我将实现一个非常基本的模块,当它被装载时将打印出一条信息,并在被卸载的时候打印出另外的一条信息。我还将概述使用标准工具手工编译我们的模块以及重新构建现有的FreeBSD内核的过程。我们开始吧!
入门
本文需要具备一些必要条件。我假定认为你具备一定的C编程知识,尽管没有太复杂的内容。如果我提及一个指针或者一个结构,我希望你不需要太多的解释就能理解那些概念。我还希望你熟悉类Unix操作系统并了解基本的Shell相关用法。
首先要做的事情是确信你工作将会用到的开发环境已经包括了你要用的所有的东西并正确地被配置好了。我将会认为你已经安装好并正在运行着FreeBSD。如果你没有并想要一些指导的话,你可以阅读我的这篇文章:Secure emails servers with FreeBSD。我会以不同方式做一些事情;所以,我会建议你把它当作安装的资料,这对这两篇文章都是一样的。
你还将需要确信你已经安装了sudo实用程序并已经为你主要使用的用户帐户做好了相关配置。kldload和kldunload实用程序将需要用它来进行以“root”运行的操作。Sudo的FreeBSD port在/usr/ports/security/sudo下。
# 请留意这一行,复制这行并把“root”用户名改成你主要使用的用户名。
如我最近的一篇文章Review of FreeBSD 7.0中所提到的那样,ULE调度器给FreeBSD带来了新级别的性能以及多处理器的伸缩性。尽管其已经被认为稳定并已经是最佳时期,但在7.1发行版之前它默认是不被启用的。对你的安装水平的最好的实测将是编译一个启用ULE调度器的定制内核。
如果你正使用基于x86架构的机器,内核位于/usr/src/sys/i386目录下。对于amd64机器而言,只需要把i386换成amd64,也就是/usr/src/sys/amd64。内核配置文件位于一个叫做conf的目录。进入该目录并通过拷贝“generic”默认配置文件为一个我们命名的名字来创建你的定制内核配置文件。
用你选择的文本编辑器打开“CUSTOM”文件然后找到启用旧版44BSD调度器的那行并将其替换成ULE。在现有的内核配置文件中它应该在第30行左右(在我写这篇文章的时候)。
注意:如果你是在VMWare中运行的FreeBSD,这里有个非常重要的性能设置来使你的系统适合本文。内核计时器的频率需要从“1000”降低到“100”次每秒。用你喜爱的编辑器编辑/boot/loader.conf文件并添加如下内容:
你可能已经注意到了,FreeBSD在构建以及安装内核(还有操作系统的其余任务)中有效地使用了make程序。你可能还不知道吧,但你将不会惊讶了,FreeBSD开发者还开发了一些makefile来简化了困难的内核模块开发。
对makefile以及make程序更深入地研究都超出了本文的范围。然而,直接相关的两点是bsd.kmod.mk这个makefile以及它能够与其他的makefile两者相互包括在内。
bsd.kmod.mk这个makefile位于/usr/src/share/mk/bsd.kmod.mk,它使所有的痛苦远离正确地构建并连接内核模块。如你即将看到的,你只不过需要设置两个变量:
然后,你所必须做的所有事情就是使用include包含进bsd.kmod.mk文件来构建该模块。这个简明的设置使得你只需要用以下骨架makefile并简单地通过“make”程序调用即可着手构建你的内核模块。
我们入门的内核模块的Makefile类似于这样的内容:
创建一个模块
现在你有个关于构建环境的提示,是时候来看看一个FreeBSD内核模块背后的实际代码以及在运行中的内核插入和移除一个模块的机制了。
内核模块允许动态功能性添加到一个运行中的内核中。当一个内核模块被插入,“load”事件被触发。当一个内核模块被移除时,“unload”事件被触发。内核模块负责实现一个处理相关情况的时间处理器。
运行中的内核将传入/usr/include/sys/module.h()头文件中所定义的符号常量框架中的事件。MOD_LOAD以及MOD_UNLOAD这两个主要的事件是你需要关心的。
运行中的内核如何象调用传递参数一样来获知某个函数调用并传递一个事件类型呢?模块负责使用DECLARE_MODULE宏来将逆向调用配置好。
DECLARE_MODULE宏在头文件的117行中定义。其使用了下面的四个参数:
这个moduledata结构包括了定义为一个char变量的名字和一般情况下在中第50行所定义modeventhand_t结构的事件处理器。最后,对额外的数据而言,moduledata结构拥有一个空的指针,你将不可以使用它。
也许你看着这篇上下文不包括任何代码的概述脑子都快要炸了,别怕。那都是在你开始编写内核模块前所需要知道的一个综述,所以会那样,“好朋友们,再接再厉,向缺口冲去吧!”在你开始之前,确信你在与之前创建好的Makefile文件相同的内核目录,启动你所选择的文本编辑器并打开一个叫做hello_fsm.c的文件。
首先将所使用的数据类型所需求的头文件包括进去。你已经看到了以及其他的include语句都是所支持的头文件。
DECLARE_MODULE(hello_fsm, hello_conf, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
其他所需要做的也就是构建模块了。反复查看你正和模块的makefile处于同一目录并简单地执行:
要装载该模块,你有两个选择:使用kldload实用程序或者是通过makefile装载make目标。所以不管你选择哪个都必须通过使用“sudo”程序来获取装载和卸载内核模块所需要的root权限。
想要卸载该模块的话,使用kldunload或者是makefile中的卸载目标。你应该会看到MOD_UNLOAD事件时的所打印出的信息,也就是“Bye Bye FSM reader, be sure to check http://freesoftwaremagazine.com !”
结语
现在你有了一个基本的,骨架的内核模块。它在被装载是打印一条信息以及在被从内核中卸载时打印出另外一条单独的信息。本文涵盖了构建、插入和移除模块的技巧。你知道了最基本的知识积累来对付更加高级的项目:我想建议你看一下写字符设备的作家的文章,因为它恐怕是最简单的设备驱动了吧。
希望这带给了你如同这曾带给过我的无穷乐趣!
入门
本文需要具备一些必要条件。我假定认为你具备一定的C编程知识,尽管没有太复杂的内容。如果我提及一个指针或者一个结构,我希望你不需要太多的解释就能理解那些概念。我还希望你熟悉类Unix操作系统并了解基本的Shell相关用法。
首先要做的事情是确信你工作将会用到的开发环境已经包括了你要用的所有的东西并正确地被配置好了。我将会认为你已经安装好并正在运行着FreeBSD。如果你没有并想要一些指导的话,你可以阅读我的这篇文章:Secure emails servers with FreeBSD。我会以不同方式做一些事情;所以,我会建议你把它当作安装的资料,这对这两篇文章都是一样的。
你还将需要确信你已经安装了sudo实用程序并已经为你主要使用的用户帐户做好了相关配置。kldload和kldunload实用程序将需要用它来进行以“root”运行的操作。Sudo的FreeBSD port在/usr/ports/security/sudo下。
- cd /usr/ports/security/sudo
- make install && make clean
- su
- visudo
# 请留意这一行,复制这行并把“root”用户名改成你主要使用的用户名。
- root ALL=(ALL) SETENV: ALL
- yourabi ALL=(ALL) SETENV: ALL
如我最近的一篇文章Review of FreeBSD 7.0中所提到的那样,ULE调度器给FreeBSD带来了新级别的性能以及多处理器的伸缩性。尽管其已经被认为稳定并已经是最佳时期,但在7.1发行版之前它默认是不被启用的。对你的安装水平的最好的实测将是编译一个启用ULE调度器的定制内核。
如果你正使用基于x86架构的机器,内核位于/usr/src/sys/i386目录下。对于amd64机器而言,只需要把i386换成amd64,也就是/usr/src/sys/amd64。内核配置文件位于一个叫做conf的目录。进入该目录并通过拷贝“generic”默认配置文件为一个我们命名的名字来创建你的定制内核配置文件。
- cd /usr/src/sys/amd64/conf
- cp GENERIC CUSTOM
用你选择的文本编辑器打开“CUSTOM”文件然后找到启用旧版44BSD调度器的那行并将其替换成ULE。在现有的内核配置文件中它应该在第30行左右(在我写这篇文章的时候)。
- options SCHED_4BSD # 4BSD scheduler
- # 改为 #
- options SCHED_ULE # ULE scheduler
- cd /usr/src
- make buildkernel KERNCONF="CUSTOM"
- make installkernel KERNCONF="CUSTOM"
- reboot
注意:如果你是在VMWare中运行的FreeBSD,这里有个非常重要的性能设置来使你的系统适合本文。内核计时器的频率需要从“1000”降低到“100”次每秒。用你喜爱的编辑器编辑/boot/loader.conf文件并添加如下内容:
- echo kern.hz=100 >> /boot/loader.conf
你可能已经注意到了,FreeBSD在构建以及安装内核(还有操作系统的其余任务)中有效地使用了make程序。你可能还不知道吧,但你将不会惊讶了,FreeBSD开发者还开发了一些makefile来简化了困难的内核模块开发。
对makefile以及make程序更深入地研究都超出了本文的范围。然而,直接相关的两点是bsd.kmod.mk这个makefile以及它能够与其他的makefile两者相互包括在内。
bsd.kmod.mk这个makefile位于/usr/src/share/mk/bsd.kmod.mk,它使所有的痛苦远离正确地构建并连接内核模块。如你即将看到的,你只不过需要设置两个变量:
- 通过“KMOD”变量设置内核模块名;
- 通过直观的“SRCS”变量设置配置好的源文件;
然后,你所必须做的所有事情就是使用include
我们入门的内核模块的Makefile类似于这样的内容:
- # Note: It is important to make sure you include the
makefile after declaring the KMOD and SRCS variables.
-
- # Declare Name of kernel module
- KMOD = hello_fsm
-
- # Enumerate Source files for kernel module
- SRCS = hello_fsm.c
-
- # Include kernel module makefile
- .include
创建一个模块
现在你有个关于构建环境的提示,是时候来看看一个FreeBSD内核模块背后的实际代码以及在运行中的内核插入和移除一个模块的机制了。
内核模块允许动态功能性添加到一个运行中的内核中。当一个内核模块被插入,“load”事件被触发。当一个内核模块被移除时,“unload”事件被触发。内核模块负责实现一个处理相关情况的时间处理器。
运行中的内核将传入/usr/include/sys/module.h(
运行中的内核如何象调用传递参数一样来获知某个函数调用并传递一个事件类型呢?模块负责使用DECLARE_MODULE宏来将逆向调用配置好。
DECLARE_MODULE宏在
- name. 定义名字
- data. 指定moduledata_t结构的名字,在我的实现过程中我已经将其命名为hello_conf。moduledata_t类型被定义在
的第55行。稍后我将简要说明。 - sub. 设定子系统接口,它定义了模块的类型。
- order. 在被定义的子系统中定义模块初始化顺序。
这个moduledata结构包括了定义为一个char变量的名字和一般情况下在
也许你看着这篇上下文不包括任何代码的概述脑子都快要炸了,别怕。那都是在你开始编写内核模块前所需要知道的一个综述,所以会那样,“好朋友们,再接再厉,向缺口冲去吧!”在你开始之前,确信你在与之前创建好的Makefile文件相同的内核目录,启动你所选择的文本编辑器并打开一个叫做hello_fsm.c的文件。
首先将所使用的数据类型所需求的头文件包括进去。你已经看到了
- #include
- #include
- #include
- #include
- /* The function called at load/unload. */
- static int event_handler(struct module *module, int event, void *arg) {
- int e = 0; /* Error, 0 for normal return status */
- switch (event) {
- case MOD_LOAD:
- uprintf("Hello Free Software Magazine Readers! \n");
- break;
- case MOD_UNLOAD:
- uprintf("Bye Bye FSM reader, be sure to check http://freesoftwaremagazine.com !\n");
- break;
- default:
- e = EOPNOTSUPP; /* Error, Operation Not Supported */
- break;
- }
-
- return(e);
- }
- /* The second argument of DECLARE_MODULE. */
- static moduledata_t hello_conf = {
- "hello_fsm", /* module name */
- event_handler, /* event handler */
- NULL /* extra data */
- };
DECLARE_MODULE(hello_fsm, hello_conf, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
其他所需要做的也就是构建模块了。反复查看你正和模块的makefile处于同一目录并简单地执行:
- make
要装载该模块,你有两个选择:使用kldload实用程序或者是通过
- sudo kldload ./hello_fsm.ko
- # 或者 #
- sudo make load
kldstat
Id Refs Address Size Name
1 8 0xc0400000 926ed4 kernel
2 1 0xc0d27000 6a1c4 acpi.ko
3 1 0xc317e000 22000 linux.ko
4 1 0xc4146000 2000 hello_fsm.ko
想要卸载该模块的话,使用kldunload或者是
sudo kldunload hello_fsm
或者
sudo make unload
结语
现在你有了一个基本的,骨架的内核模块。它在被装载是打印一条信息以及在被从内核中卸载时打印出另外一条单独的信息。本文涵盖了构建、插入和移除模块的技巧。你知道了最基本的知识积累来对付更加高级的项目:我想建议你看一下写字符设备的作家的文章,因为它恐怕是最简单的设备驱动了吧。
希望这带给了你如同这曾带给过我的无穷乐趣!
为FreeBSD编写内核模块
玩转freebsd内核模块 - 网文收集 - 一粒沙子的空间
内核模块 编写及编译 内核树的建立 一些调试内容
FreeBSD 内核网络处理流程分析
内核模块加载命令
Linux内核驱动模块
在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序
Asterisk模块编写1
Asterisk模块编写2
编写最简单的Linux模块
Linux 2.6内核的编译步骤及模块的动态加载 - 内核源码学习 - Linux论坛
小白学Linux之内核模块编程 - tiger-john - CSDN博客
内核模块相关命令:lsmod,depmod,modprob等
Linux内核模块导出后无法调用问题解决(模块间函数调用通讯)
为你导航模块
为单点登录身份验证编写 OpenID 提供者
FreeBSD 安装图文示例
为Word2010编写宏 快速打印当前文档页
skyeye下执行为uClinux编写的程序
FreeBSD top命令详解 - FreeBSD - 吃鱼翅的鱼
使用netfilter/iptables为Linux(内核2.4.x)配置防火墙
FreeBSD ULE调度器浅析
浏览器内核
Windows内核