添加驱动模块到内核的两种方法

添加驱动模块到内核的两种方法

1. 放在内核源代码树中

步骤总结:

  1. 新建文件夹
  2. 编写Makefile、编写Kconfig
  3. 修改上层Kconfig
  4. 执行make menuconfig
  5. 执行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.
    
  1. 第一行定义了该选项所代表的配置目标(注意 CONFIG_ 前缀不必写上)

  2. 第二行声明选项类型为 “tristate” ,它有三个选项N Y M,Y表示可以编译进内核,M表示作为模块编译,N表示不操作。

  3. 第三行是默认的选项类型

  4. help 表示为该选项提供帮助文档

  5. 除了上述选项外,还有其他选项,比如 depends 指令,规定了该选项的依赖选项,表示必须将依赖选项设置,才可以选择本选项

    depends on MENU_KEY

  6. 在 drivers/char/Kconfig 文件中添加

    source “drivers/char/mykey/Kconfig”

执行 make menuconfig 后结果如下
添加驱动模块到内核的两种方法_第1张图片

如果 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(可以看到多出一个菜单来)
添加驱动模块到内核的两种方法_第2张图片

按 “h” 进入 help
添加驱动模块到内核的两种方法_第3张图片
make menuconfig 之前看一眼内核根目录下的 .config 文件, CONFIG_MYKEY 还未定义

添加驱动模块到内核的两种方法_第4张图片
我们使用 make menuconfig 将 CONFIG_MYKEY 选项选择为 M 后,看一下内核目录下的 .config 文件
添加驱动模块到内核的两种方法_第5张图片

别忘了在 drivers/char/mykey/Makefile 中添加内容

obj-$(CONFIG_MYKEY) += mykey.o

make modules 后观察 drivers/char/mykey/ 目录下的文件,多出了许多文件,其中包括 key.ko
添加驱动模块到内核的两种方法_第6张图片

如果要编译进内核中, 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

你可能感兴趣的:(Linux内核深入浅出,内核,驱动,模块,make,Kconfig,Makefile,menuconfig)