内核模块化编程

目录

内核模块的概念介绍

动态模块化编程框架

模块加载函数

模块卸载函数

模块的开源协议与声明

模块编译 Makefile 模板

单模块的编程步骤

1 编写内核模块文件test.c

2 编写Makefile

3 编译生成test.ko


内核模块的概念介绍

Linux 内核整体结构已经很庞大,包含了很多的组件,而对于我们工程师而言,有两种方法将需要的功能包含进内核当中。
        一:将所有的功能都编译进 Linux 内核(静态加载模块)。
        二:将需要的功能编译成模块,在需要的时候动态地添加(动态加载模块)。
上述两种方式优缺点分析:
        第一种:优点:不会有版本不兼容的问题,不需要进行严格的版本检查缺点:生成的内核会很大;要在现有的内核中添加新的功能,则要编译整个内核
        第二种:优点:模块本身不编译进内核,从而控制了内核的大小;模块一旦被加载,将和其它的部分完全一样。缺点:可能会有内核与模块版本不兼容的问题,导致内核崩溃;会造成内存的利用率比较低。

在超级终端MobaXterm 使用模块常用命令

#insmod xxx.ko//将模块添加进内核
#rmmod xxx.ko//将模块从内核卸载
#lsmod //查看已安装到内核的模块
#modprobe //载入指定的个别模块,或是载入一组相依赖的模块。 modprobe 会根据 depmod 所
//产生的依赖关系,决定要载入哪些模块。若在载入 过程中发生错误,在 modprobe 会卸载整
//组的模块。依赖关系是通过读取 /lib/modules/2.6.xx/modules.dep 得到的。而该文件是通过
//depmod 所建立。
#modinfo //查看模块信息。使用方法: #modinfo XXX.ko
#tree –a //查看当前目录的整个树结构

动态模块化编程框架

模块加载函数

static int __init XXX_init(void)//加载函数
{
    //注册设备hello
	return 0;
}
moudle_init(XXX_init); // 当执行#insmod 或者#modprobe 时调用,可以看作模块的入口

        当#insmod xxx.ko时会调用 module_init所修饰的 XXX_init函数来完成一些初始化操作(xxx在写代码时要根据实际模块进行修改)Linux 内核的模块加载函数一般用__init 标识声明,用于告诉编译器相关函数或变量仅用于初始化,初始化结束后就释放这段内存。XXX_init 函数的返回值为一个整形的数,如果执行成功,则返回 0,初始化失败时则返回错误编码, Linux 内核当中的错误编码是负值,在<linux/errno.h>中定义

模块卸载函数

static void __exit XXX_exit(void)
{ }
moudle_exit(XXX_exit); // 执行#rmmod 时调用

        在用 rmmodmodprobe 命令卸载模块时,该函数被执行。完成与加载相反的工作。模块的卸载函数和模块加载函数实现相反的功能,主要包括:
1) 若模块加载函数注册了 XXX,则模块卸载函数注销 XXX
2) 若模块加载函数动态分配了内存,则模块卸载函数释放这些内存
3) 若模块加载函数申请了硬件资源,则模块卸载函数释放这些硬件资源
4) 若模块加载函数开启了硬件资源,则模块卸载函数一定要关闭这些资源

模块的开源协议与声明

MODULE_LICENSE("GPL");

GPL 协议介绍:全称为 GNU General Public Licence, GPL 保证了所有开发者的权利(开发者拥有版权和专利),同时为使用者提供了足够的复制、分发和修改的权利:
1)使用者可以自由复制软件到任何地方
2) 使用者可自由分发源代码或者二进制文件
3) 使用者可以用来盈利, 但必须想客户提供该软件的 GNU GPL 许可协议,以便让他们知道,他们可以从别的渠道免费得到这份软件,以及你收费的理由
4) 使用者可自由修改软件,如果使用者想添加或删除某个功能,没问题,如果你想在别的项目中使用部分代码,也没问题,唯一的要求是,使用了这段代码的项目也必须使用 GPL协议

非必须的模块声明

MODULE_AUTHOR       // 声明作者
MODULE_DESCRIPTION  // 对模块简单的描述
MODULE_VERSION      // 声明模块的版本
MODULE_ALIAS        // 模块的别名
MODULE_DEVICE_TABLE // 告诉用户空间这个模块所支持的设备

模块编译 Makefile 模板

# Makefile 2.6 模板
#当make的目标为all时,-C $(KDIR) 指明跳转到内核源码目录下读取那里的Makefile;
#obj-m表示把文件hello.o作为"模块"进行编译,不会编译到内核,但是会生成一个独立的 "hello.ko" 文件;
#M=$(PWD) 表明然后返回到当前目录继续读入、执行当前的Makefile。
obj-m += hello.o
#在使用时KDIR要修改为你自己的内核的顶级目录
KDIR:= /3linux/linux-3.5
all:
	make -C $(KDIR) M=$(PWD) modules
#-C 选项的作用是指将当前工作目录转移到你所指定的位置。
#“M=”选项的作用是,当用户需要以某个内核为基础编译一个外部模块的话,
#需要在make modules 命令中加入“M=dir”,
#程序会自动到你所指定的dir目录中查找模块源码,将其编译,生成KO文件。
clean:
	rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.markers *.order
#使用make命令编译模块,由于makefile文件无法正确的处理带空格的路径名,
#确保路径没有空格符
#该命令是make modules命令的扩展,-C选项的作用是指将当前的工作目录转移到制定的 目录,即(KDIR)目录,程序到(shellpwd)当前目录查找模块源码,将其编译,生成.ko文件

单模块的编程步骤

1 编写内核模块文件test.c

#include<linux/kernel.h>
#include<linux/module.h>
static int __init test_init(void)  //加载函数
{
    printk("this is test file!\n");
	return 0;
}
static void __exit test_exit(void) //卸载函数
{
    printk("exit!\n");
}
module_init(test_init); //声明加载函数
module_exit(test_exit); //声明卸载函数
MODULE_LISENSE("GPL"); //声明开源协议

2 编写Makefile

obj-m += test.o
KDIR:=/root/tiny4412/linux-3.5/

all:
	make -C $(KDIR) M=$(PWD) modules
clean:
	rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.markers *.order

3 编译生成test.ko

在虚拟机终端中输入命令make,生成模块文件test.ko。将 test.ko 拷贝到根文件系统,在开发板的终端中执行

insmod test.ko //加载test模块
lsmod          //查看当前挂载模块
rmmod test.ko  //卸载test模块

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值