添加驱动模块到内核的两种方法
1. 放在内核源代码树中
步骤总结:
- 新建文件夹
- 编写Makefile、编写Kconfig
- 修改上层Kconfig
- 执行make menuconfig
- 执行make zImage 或 make modules
1.1 源码放入文件夹
例如:添加一个按键字符设备模块
-
在内核目录下的 drivers/char 目录下新建文件夹 mykey
-
在 drivers/char/ 下的 Makefile 中添加一行
obj-m += mykey/ 这行指令告诉模块构建系统,在编译模块时需要进入 mykey/ 子目录中 有可能的选择是,驱动程序的编译取决于一个特殊的配置选项,例如 CONFIG_MYKEY ,则指令要替换成 obj-$(CONFIG_MYKEY) += mykey/
-
最后,在 drivers/char/mykey/ 目录下添加一个 Makefile,其中需要有下面这行指令
obj-m += mykey.o 表示进入 mykey/ 子目录后,要将 mykey.c 编译成 mykey.o,但最终会生成 mykey.ko 文件 如果加了编译选项,则指令如下 obj-$(CONFIG_MYKEY) += mykey.o
-
另外,如果后续你的按键程序需要使用到其他的源文件,可以将 mykey/ 目录下的 Makefile 做如下修改
obj-$(CONFIG_MYKEY) += mykey.o mykey-objs := mykey_main.o other.o 表示 mykey_main.c 和 other.c 会一起被编译和链接进 mykey.ko 文件
1.2 源码放入设备总目录下
如果只有一两个源文件,则可以选择不新建文件夹,直接将 mykey.c 放入到 drivers/char/ 目录下,在 drivers/char/ 目录下的 Makefile 中添加如下指令即可
obj-m += mykey.o
如果配置了编译选项,则指令为
obj-$(CONFIG_MYKEY) += mykey.o
如果有多个源文件,则指令为
obj-$(CONFIG_MYKEY) += mykey.o
mykey-objs := mykey_main.o other.o
即将原本 drivers/char/mykey/Makefile 的内容全部写到 drivers/char/Makefile 中。
1.3 管理配置选项
-
在 drivers/char/mykey/ 目录下新建一个 Kconfig 文件(如果没有独立目录,则直接在 drivers/char/Kconfig 中添加)
-
添加如下内容(实例)
config MYKEY tristate "This is config of mykey" default n help If you chose Y, support this key function, this key will be compiledinto the kernel. you can also chose M, then this driver will be built as a module named mykey.ko.
-
第一行定义了该选项所代表的配置目标(注意 CONFIG_ 前缀不必写上)
-
第二行声明选项类型为 “tristate” ,它有三个选项N Y M,Y表示可以编译进内核,M表示作为模块编译,N表示不操作。
-
第三行是默认的选项类型
-
help 表示为该选项提供帮助文档
-
除了上述选项外,还有其他选项,比如 depends 指令,规定了该选项的依赖选项,表示必须将依赖选项设置,才可以选择本选项
depends on MENU_KEY
-
在 drivers/char/Kconfig 文件中添加
source “drivers/char/mykey/Kconfig”
执行 make menuconfig 后结果如下
如果 Kconfig 的内容改成这样(带菜单)
menu "Config my key"
config MYKEY
tristate "This is config of mykey"
default n
help
If you chose Y, support this key function,
this key will be compiledinto the kernel.
you can also chose M, then this driver will
be built as a module named mykey.ko.
endmenu
make menuconfig 找到 MYKEY(可以看到多出一个菜单来)
按 “h” 进入 help
make menuconfig 之前看一眼内核根目录下的 .config 文件, CONFIG_MYKEY 还未定义
我们使用 make menuconfig 将 CONFIG_MYKEY 选项选择为 M 后,看一下内核目录下的 .config 文件
别忘了在 drivers/char/mykey/Makefile 中添加内容
obj-$(CONFIG_MYKEY) += mykey.o
make modules 后观察 drivers/char/mykey/ 目录下的文件,多出了许多文件,其中包括 key.ko
如果要编译进内核中, CONFIG_MYKEY 选项选择为 Y ,然后执行 make zImage,会发现生成的zImage镜像大小增加了一些,但是不会在 drivers/char/mykey/ 下生成 key.ko ,不过会生成 key.o
PS:obj-y(对应 make zImage))是指将模块编译进内核(zImage)
obj-m(对应 make modules)是指编译模块生成 ko 文件
2. 放在内核代码外
如果我们希望编写的模块可以被动态的加载到内核中,即使用 insmod、modprobe 命令,则不能将模块代码直接放入内核源码树中了。
只需在自己编写的模块目录中新建一个 Makefile 文件,由于是在内核源码外围,所以我们需要告诉 make 工具如何找到内核源代码文件和基础的 Makefile 文件
为什么需要找到内核源码和基础 Makefile 文件?
答:因为驱动代码中使用到了内核提供的函数、头文件等等,编译成最终的 ko 文件也是要遵循内核的编译方法
Makefile 中一定要包含以下指令
make -C 内核所在路径 M=$PWD modules
obj-m += mykey.o
一般的 Makefile 的写法如下:
KERN_DIR = /home/内核路径
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
obj-m += mykey.o
执行make后,生成mykey.ko文件,使用动态加载命令插入进内核
insmod mykey.ko