《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #3 如何编写内核模块
HACK #3 如何编写内核模块
本节将介绍向Linux内核中动态添加功能的结构—内核模块的编写方法。
内核模块
Linux内核是单内核(monolithic kernel),也就是所有的内核功能都集成在一个内核空间内。但是内核具有模块功能,可以将磁盘驱动程序、文件系统等独立的内核功能制作成模块,并动态添加到内核空间或者删除。
内核模块是可以动态添加到Linux内核空间的二进制文件,文件扩展名为ko。
内核模块的编写方法大致有两种。一种是将内核源码树带有的功能编写为模块的方法(参考Hack #2),另一种是将内核源码树中所没有的特有功能编写为模块的方法。
通过内核配置编写模块
把内核源代码文件中CONFIG_*=m的项目所对应的驱动程序编写为模块。编写生成的模块一般安装在/lib/modules/内核版本/kernel下。
以RHEL6为例
# ls /lib/modules/2.6.32-71.29.1.el6.x86_64/kernel/
arch crypto drivers fs kernel lib mm net sound
编写特有的内核模块
下面将介绍如何编写内核源码树中所没有的特有内核模块。
以mymod模块为例说明,请将下面的代码以mymod.c为文件名保存。
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/errno.h>
static int sec = 5;
module_param(sec, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(sec, "Set the interval.");
static void mymod_timer(unsigned long data);
static DEFINE_TIMER(timer, mymod_timer, 0, 0);
static void mymod_timer(unsigned long data)
{
printk(KERN_INFO "mymod: timer\n");
mod_timer(&timer, jiffies + sec * HZ);
}
static int mymod_init(void)
{
printk(KERN_INFO "mymod: init\n");
if (sec <= 0) {
printk(KERN_INFO "Invalid interval sec=%d\n", sec);
return -EINVAL;
}
mod_timer(&timer, jiffies + sec * HZ);
return 0;
}
static void mymod_exit(void)
{
del_timer(&timer);
printk(KERN_INFO "mymod: exit\n");
}
module_init(mymod_init);
module_exit(mymod_exit);
MODULE_AUTHOR("Hiroshi Shimamoto");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("My module");
在模块的源代码中包含(include)头文件linux/module.h。
名为module_int()和module_exit()的宏,可以调用回调(callback)函数来进行初始化和终止模块的处理。在模块的源文件中进行如下描述,就可以在添加模块时调用初始化函数,在删除模块时调用终止函数。
module_init(初始化函数名);
module_exit(终止函数名);
在这个例子模块的情形下调用的分别是mymod_init()和mymod_exit()。
初始化函数为了表示初始化已正常完成,需要返回0。按照Linux内核中的写法,发生错误(error)时将返回一个值为负数的错误代码。在这个例子中,如果设定值出错,则处理为-EINVAL(非法值)。
下面先用3个宏对模块进行定义,但在模块编写中并不是必需的。
这个例子模块还用到了模块参数。模块参数可以使用module_param()宏来生成。
module_param(参数名,参数类型,权限(permission));
在例子模块中,sec定义为int类型的模块参数。
另外,还可以使用MODULE_PARM_DESC()宏来对模块参数进行说明。
先简单介绍一下这个例子的运行过程。当添加模块时,会调用指定为初始化函数的mymod_init()。在mymod_init()中首先通过printk()输出:
mymod: init
然后确认模块参数sec是否正常。在模块参数sec的值为0以下的异常情形时,会返回EINVAL错误代码并终止程序。在判断模块参数sec正常后,将内核计时器设置为sec秒后启动超时(timeout)函数mymod_timer()。在每隔sec秒启动的mymod_timer()中,首先使用printk()输出:
mymod: timer
再次设置sec秒的内核计时器,然后终止。当删除模块时,会调用mymod_exit()函数,删除内核计时器,通过printk()输出:
mymod: exit
于是模块终止。
接下来需要准备编写模块所需的Makefile。由于是使用内核的创建框架来生成,因此Makefile的内容非常简单。
obj-m :=mymod.o
最后执行下列make命令,通过当前目录(current directory)的源代码和Makefile生成模块mymod.ko。
# make -C /lib/modules/'uname 杛'/build M='pwd'
通过使用modinfo命令,可以看到所生成模块mymod.ko的信息。从这里可以看到使用MODULE_*宏所指定的内容。
# modinfo mymod.ko
filename: mymod.ko
description: My module
license: GPL
author: Hiroshi Shimamoto
srcversion: 61A3BB7CFC0C89B8344F5A5
depends:
vermagic: 2.6.32-71.29.1.el6.x86_64 SMP mod_unload modversions
parm: sec:Set the interval. (int)
添加内核模块
添加内核模块需要用到insmod命令或modprobe命令。
通过执行insmod命令把生成的mymod.ko模块添加进来。
# insmod mymod.ko
使用dmesg命令,可以看到例子模块mymod.ko的输出内容。
# dmesg | tail
:
mymod: init
作为模块初始化函数mymod_init()所调用的printk()的输出内容会在最后一行显示。
使用lsmod可以显示目前添加到内核中的模块列表。
# lsmod
Module Size Used by
mymod 1482 0
:
可以看到,mymod行存在,模块已添加。
要将已添加的模块从内核空间删除时,可以使用rmmod命令。
# rmmod mymod
执行rmmod命令后,模块将从内核空间内删除,使用lsmod命令就不会再输出mymod行。
此外,使用dmesg命令还可以看到终止模块的处理中printk()输出的信息mymod: exit。
# dmesg | tail
:
mymod: exit
下面针对模块参数作一些介绍。在添加模块后,就会在/sys/module下生成对应的目录和文件。
# ls /sys/module/mymod/
holders initstate notes parameters refcnt sections srcversion
可以确认在parameters下生成的模块mymod中所定义的参数sec。
# ls -l /sys/module/mymod/parameters/sec
-rw-r--r--. 1 root root 4096 May 15 06:34 /sys/module/mymod/parameters/sec
其内容应当是初始值5。
# cat /sys/module/mymod/parameters/sec
5
模块参数可以在使用insmod添加模块时对值进行指定。
# insmod mymod.ko sec=10
进行上述操作后,添加mymod.ko时模块参数sec就为10,默认间隔5秒的超时变成间隔10秒。
小结
本节介绍了内核模块的编写方法。编写特有内核模块是Kernel构建的入门级操作,你也可以尝试一下。
参考文献
Documentation/kbuild/modules.txt
—Hiroshi Shimamoto
《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #3 如何编写内核模块的更多相关文章
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #1 如何获取Linux内核
HACK #1 如何获取Linux内核 本节介绍获取Linux内核源代码的各种方法.“获取内核”这个说法看似简单,其实Linux内核有很多种衍生版本.要找出自己想要的源代码到底是哪一个,必须首先理解各 ...
- 《Linux内核精髓:精通Linux内核必会的75个绝技》目录
1章 内核入门HACK #1 如何获取Linux内核HACK #2 如何编译Linux内核HACK #3 如何编写内核模块HACK #4 如何使用GitHACK #5 使用checkpatch.pl检 ...
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #15 ramzswap
HACK #15 ramzswap 本节介绍将一部分内存作为交换设备使用的ramzswap.ramzswap是将一部分内存空间作为交换设备使用的基于RAM的块设备.对要换出(swapout)的页面进行 ...
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #21FUSE
HACK #21FUSE 本节将介绍使用用户进程的文件系统框架—FUSE.FUSE概要FUSE(Filesystem in Userspace,用户空间文件系统),是用来生成用户空间的一般进程的框架. ...
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #20 使用fio进行I/O的基准测试
HACK #20 使用fio进行I/O的基准测试 本节介绍使用fio进行模拟各种情况的I/O基准测试的操作方法.I/O的基准测试中有无数需要考虑的因素.是I/O依次访问还是随机访问?是通过read/w ...
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #17 如何使用ext4
HACK #17 如何使用ext4 本节介绍ext4的编写和挂载方法.开发版ext4的使用方法.ext4是ext3的后续文件系统,从Linux 2.6.19开始使用.现在主要的发布版中多数都是采用ex ...
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #16 OOM Killer的运行与结构
HACK #16 OOM Killer的运行与结构(1) 本节介绍OOM Killer的运行与结构. Linux中的Out Of Memory(OOM) Killer功能作为确保内存的最终手段,可以在 ...
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #14 虚拟存储子系统的调整
HACK #14 虚拟存储子系统的调整 本节介绍如何使用/proc进行虚拟存储子系统的调整.虚拟空间存储方式在Linux上向应用程序分配内存时,是通过以页面为单位的虚拟存储方式进行的.采用虚拟存储方式 ...
- 《Linux内核精髓:精通Linux内核必会的75个绝技》一HACK #13 使用Block I/O控制器设置I/O优先级
HACK #13 使用Block I/O控制器设置I/O优先级 本节介绍使用Block I/O控制器的功能设置I/O优先级的方法.Block I/O控制器可以将任意进程分组,并对该分组设置I/O的优先 ...
随机推荐
- 安装lua 环境
lua下载地址:https://www.lua.org/download.html curl -R -O http://www.lua.org/ftp/lua-5.3.5.tar.gz tar zxf ...
- Tornado教程目录
第一章:引言 第二章:表单和模板 第三章:模板扩展 第四章:数据库 第五章:异步Web服务 第六章:编写安全应用 第七章:外部服务认证 第八章:部署Tornado
- 2018-2019-2《网络对抗技术》Exp0 Kali安装 Week1
2018-2019-2<网络对抗技术>Exp0 Kali安装 Week1 Kali的安装 设置虚拟机的名称和操作系统 为虚拟机分配虚拟内存,大小为4096M,分配存储空间,大小为25.0G ...
- HTML5里的placeholder属性
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- Java Web编程的主要组件技术——Hibernate核心组件
参考书籍:<J2EE开源编程精要15讲> Hibernate配置文件 1) hibernate.cfg.xml <?xml version='1.0' encoding='UTF-8 ...
- 面筋: 奇虎360 c++ 后台开发 实习生 面试
投的是360上海的商业化部门,岗位是C++服务端开发实习生,记录一下面试历程: 视频面试,但是是有代码框让你写代码的. 一面: Q:先说一下个人信息,做过的项目 A:.......... Q:先写个翻 ...
- STL标准库-容器-forward_list
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性. forward_list即单向list,功能少额外开销就小.而且只能在前段插入元素 结构如下 一 定义 #include &l ...
- Nginx的负载均衡和高可用
一.Nginx的理解 Nginx是一个高性能的HTTP和反向代理服务,也是一个IMAP/POP3/SMTP服务.Nginx是一款轻量级的web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理 ...
- ubuntu遇到的问题
昨天分辨率在装一个游戏时被更改了,改过之后,怎么都改不过来... 折腾了一下午,在配置文件中/etc/X11/xorg.conf.failsafe,但是网上都是/etc/X11/xorg.conf, ...
- 2018-2019-2 《网络对抗技术》Exp4 恶意代码分析 20165222李勖
1.系统运行监控 (1)使用如计划任务,每隔一分钟记录自己的电脑有哪些程序在联网,连接的外部IP是哪里.运行一段时间并分析该文件,综述一下分析结果.目标就是找出所有连网的程序,连了哪里,大约干了什么( ...