超详细!手把手演示编译OpenWrt内核驱动模块
前言:构建自己的内核驱动模块,相关知识可以参考OpenWrt软件编译构建系统文章:https://blog.csdn.net/qq_41453285/article/details/102545605下面我们自己以一个自己设计的hello-kernel内核驱动模块为例,一步一步地构建出自己的驱动模块一、目录结构通常新增一 个内核驱动模块的主要步骤如下:在OPenWrt源码的pa...
·
一、前言
- 构建自己的内核驱动模块,相关知识可以参考OpenWrt软件编译构建系统文章:https://dongshao.blog.csdn.net/article/details/102545618。
- 下面我们自己以一个自己设计的hello-kernel内核驱动模块为例,一步一步地构建出自己的驱动模块。
二、目录结构
- 通常新增一 个内核驱动模块的主要步骤如下:
- 在OPenWrt源码的package/kernel目录下增加一个目录(例如hello-kernel)。
- 在hello目录下添加src目录,src目录存放模块源码和源码编译Makefile和配置文件Kconfig。
- 在hello-kernel顶层目录下增加Makefile。此Makefile中包含编译脚本和安装脚本。
- 我们软件的目录为名为hello-kernel,放置在OpenWrt源码的package/kernel目录下:
三、src目录设计
- 这个目录下存放着驱动模块的源代码hello-kernel.c、hello-kernel.c的Makefile文件、配置文件Kconfig。
Makefile文件
- 这个Makefile文件的格式都是固定的,不论是编译什么内核模块都是一样。只需要写入obj-${CONFIG_HELLO-KERNEL},然后再后面+=驱动模块名称的.o文件名即可。
- 此处我们的驱动模块Makefile如下所示:
Kconfig文件
- 这个配置文件是必须有的。
config HELLO-KERNEL tristate "Test kernel driver" help This is an Kernel Driver Test if unsure ,delete it ,just for fun
hello-kernel.c代码设计
- 此处我们只是来演示如何编译一个OpenWrt的内核驱动模块,所以驱动模块没有太多功能。单纯的知识在加载驱动模块和卸载驱动模块的时候打印一下信息,代码如下:
#include <linux/init.h> #include <linux/module.h> static int __init hello_init(void) { printk(KERN_INFO "Hello World enter\n"); return 0; } module_init(hello_init); static void __exit hello_exit(void) { printk(KERN_INFO "Hello World exit\n "); } module_exit(hello_exit); MODULE_AUTHOR("dongshao-CSDN"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("A simple Hello World Module"); MODULE_ALIAS("a simplest module");
四、顶级Makefile设计
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=hello-kernel
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
EXTRA_CFLAGS:= \
$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \
MAKE_OPTS:=ARCH="$(LINUX_KARCH)" \
CROSS_COMPILE="$(TARGET_CROSS)" \
SUBDIRS="$(PKG_BUILD_DIR)" \
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
$(EXTRA_KCONFIG)
define KernelPackage/hello-kernel
SUBMENU:=Other modules
TITLE:=Hello kernel drive
FILES:=$(PKG_BUILD_DIR)/hello-kernel.ko
AUTOLOAD:=$(call AutoProbe,81,hello-kernel)
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)/
$(CP) -R ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Compile
$(MAKE) -C "$(LINUX_DIR)" \
$(MAKE_OPTS) CONFIG_HELLO-KERNEL=m \
modules
endef
$(eval $(call KernelPackage,hello-kernel))
Makefile解析
- 第一步:首先包含rules.mk和kernel.mk文件。接着将驱动模块的名称定义为“hello-kernel”,并设置版本编号为“1”。
- 第二步:接着是编译时的一些选项,保持默认即可。
- 第三步:在软件包定义中的一些变量赋值:
- SUBMENU:我们内核模块放置于“Other modules”。我们在make menuconfig时,可以在Kernel modules/other modules菜单下找到这个模块。
- TITLE:标题,驱动模块的简短描述。
- FILES:生成的驱动模块的存放位置。此处为设置为在编译目录下(就是编译过程中的临时目录build_dir)。
- AUTOLOAD:代表是否在系统启动时自动装载到内核中,后面括号内有3个参数(参数1不变,参数2为驱动模块的装载顺序(可以省略这个参数,省略后系统自动分配状态顺序),参数3代表驱动模块名称)。
- DEPENDS:如果驱动模块还需要依赖,则此变量设置为依赖文件名(此处没有依赖所以就未设置)。
- 第四步:“Build/Prepare”定义了如何准备编译本软件包,这里创建了编译目录(OKG_BUILD_DIR就是编译过程中的临时目录build_dir),然后将src目录下的所有文件复制到编译目录下
- 第五步:编译源代码选项,在大多数情况下应该不用定义而使用默认值,下面我们加入了“CONFIG_HELLO-KERNEL=m”这一选项,MAKE_OPTS变量就是第二步图中定义的变量。
- 最后KernelPackage,将驱动模块的名称作为参数传递给KernelPackage。
五、编译驱动模块
- 第一步:打开Ubuntu,将我们的hello-kernel目录放入OpenWrt源码目录的package/kernel目录下。
- 第二步:输入“make menuconfig”进入选项菜单。
- 第三步:在OpenWrt源码顶级目录下输入下面的命令编译驱动模块。
make package/kernel/hello-kernel/compile V=s
- 第四步: 编译完成之后会在下面的目录中看到我们的内核模块(因为我们的OpenWrt内核是4.4.92版本的,所以在这个目录下)。
附加知识
- 内核的模块必须要与模块内核版本相同的系统中才可以运行,此处我们的OpenWrt源码为4.4.92版本,所以在编译完成之后生成的.ko文件也只能在4.4.92内核版本的OpenWrt中运行。
- 下面可以输入下面的命令来查看我们的OpenWr的内核版本,可以看到为4.4.92。
六、内核模块的使用
- 第一步:将我们的内核模块.ko文件发送到OpenWrt系统中。
- 第二步:输入insmod命令加载我们的内核模块,然后使用dmesg -c命令打印一下内核的输出信息。
- 第三步:输入下面命令将我们的内核模块卸载。
七、编译过程中出现的问题
问题一
- 出现下面的问题,是因为Makefile没有涉及好(空格、缩进没有做好)。
- 解决办法,将文件设置为在Unix环境下书写,并且每一行的末尾不能有多余的空格。
- 我是小董,V公众点击"笔记白嫖"解锁更多OpenWrt资料内容。
更多推荐
已为社区贡献7条内容
所有评论(0)