如何将驱动编译为kernel 模块

前言:

本文章目标平台是PC Linux,不包含其他平台。
执行下面的步骤之前,请先编译kernel通过。

linux KO编译

将驱动程序源码集成到Linux内核中:

  1. 将驱动源码文件放到drivers/net/wireless并命名

自己简单创建的几个没有任何关联的源文件:
在这里插入图片描述
并命名为:driver_test
在这里插入图片描述
任意贴一个源程序代码:dricer.c

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#define HUANGRUI  1
#define huangrui 2

MODULE_LICENSE("GPL v2");
int huangrui_function(void)
         {
                 int i=1,j=2;
                 if (i==2)
                 {
                         return 0;
                 }
                 else if(j ==3)
                 {
                         return 1;
                 }
                 else
                 {
                         return 2;
                 }

         }

其中MODULE_LICENSE(“GPL v2”);是必须要的

  1. 在drivers/net/wireless/Makefile中添加相应源码目录:

在这里插入图片描述

  1. 在drivers/net/wireless/Kconfig中添加相应Kconfig目录

在这里插入图片描述

  1. 在driver_test中创建Kconfig和Makefile

在这里插入图片描述
Konfig

 config DRIVER_TEST
      tristate  "driver_test_bool"
      depends on USB
      select USB_USBNET
      select USB_NET_CDCETHER
      default m
      help
        driver testing

Kconfig的字符解释

  • menuconfig:表示菜单(本身属于一个菜单中的项目,但是他又有子菜单项目)config表示菜单中的一个配置项(本身并没有子菜单下的项目)。一个menuconfig后面跟着的所有config项就是这个menuconfig的子菜单。这就是Kconfig中表示的目录关系。
  • source:内核源码目录树中每一个Kconfig都会用source引入其所有子目录下的Kconfig,从而保证了所有的Kconfig项目都被包含进menuconfig中。这个也说明了:如果你自己在linux内核中添加了一个文件夹,一定要在这个文件夹下创建一个Kconfig文件,然后在这个文件夹的上一层目录的Kconfig中source引入这个文件夹下的Kconfig文件。
  • tristate:意思是三态(3种状态,对应Y、N、M三种选择方式),意思就是这个配置项可以被三种选择。
  • bool:是要么真要么假(对应Y和N)。意思是这个配置项只能被2种选择。
  • depends:意思是本配置项依赖于另一个配置项。如果那个依赖的配置项为Y或者M,则本配置项才有意义;如果依赖的哪个配置项本身被设置为N,则本配置项根本没有意义。depends项会导致make menuconfig的时候找不到一些配置项。所以在menuconfig中如果找不到一个选项,但是这个选项在Kconfig中却是有的,则可能的原因就是这个配置项依赖的一个配置项是不成立的。depends依赖的配置项可以是多个,还可以有逻辑运算。这种时候只要依赖项目运算式子的结果为真则依赖就成立。
  • select:表示depends on的值有效时,下面的select也会成立,将相应的内容选上。
  • default:表示depends on的值有效时,下面的default也会成立,将相应的选项选上,有三种选项,分别对应y,n,m。
  • help:帮助信息,解释这个配置项的含义,以及如何去配置他。
    Makefile
MODULE_NAME := driver_all
$(MODULE_NAME)-y :=           \
                   driver.o     \
                   led.o        \
                   key.o
obj-$(CONFIG_DRIVER_TEST) += $(MODULE_NAME).o
  1. 使用make menuconfig命令选择宏定义
    使用"/DRIVER_TEST"查找目录:
    在这里插入图片描述
    接下来:
    在这里插入图片描述
    接下来Device Drivers —>Network device support —>driver_test_bool
    如下图:
    在这里插入图片描述
    配置好后保存,检查根目录的.config文件是否生效。
  2. 使用make命令进行全编译。
    在这里插入图片描述
  3. 如果没有报错,会生成相应的ko文件
    在这里插入图片描述

这不是正式的驱动移植,驱动移植的具体细节还要具体debug

<think>好的,用户的问题是:如何在驱动编译过程中正确调用kernel头文件?也就是驱动程序编译时如何正确包含和使用kernel头文件。我需要根据提供的引用资料来解答这个问题。 首先,用户提到的引用中有几个关键点。引用[1]指出需要一个合适的Makefile,因为编译驱动程序需要知道内核头文件和编译规则。引用[2]区分了kernel-devel和kernel-source包,前者包含头文件和Makefile,后者是完整的源代码。引用[3]提到linux-headers.deb包提供了编译内核模块所需的头文件。引用[4]则介绍了linux-images.deb和安装内核头文件的方法。引用[5]给出了编译驱动时包含头文件目录的示例命令。 接下来,我需要将这些信息整合成一个清晰的步骤指南。首先,安装正确的内核头文件包是关键,比如使用apt-get安装linux-headers-$(uname -r)。然后,编写正确的Makefile,使用类似-C指定内核路径,M指定模块路径的方式,这来自引用[5]的示例。还要注意环境变量的设置,比如ARCH和CROSS_COMPILE,这可能在某些情况下需要调整。 可能的问题点包括内核版本不一致导致头文件不匹配,这时候需要确保已安装的头文件版本与当前运行的内核版本一致。另外,交叉编译时需要配置ARCH和交叉编译工具链,这也是需要注意的地方。 用户可能遇到的常见错误是找不到头文件,这时候检查Makefile中的KERNELDIR是否正确指向头文件路径,或者是否安装了正确的头文件包。此外,权限问题也可能导致编译失败,需要使用sudo或者确保有足够的权限安装模块。 最后,生成相关问题时,需要围绕内核头文件的安装、Makefile的配置、版本匹配、交叉编译等方面提问,帮助用户进一步深入理解。</think>### 驱动程序编译时如何正确包含和使用 kernel 头文件 #### **步骤 1:安装内核头文件包** 内核头文件是编译驱动程序的**必要条件**,需确保系统中已安装与当前运行内核版本完全一致的开发包: - 在基于 Debian/Ubuntu 的系统上,使用以下命令安装: ```bash sudo apt-get install linux-headers-$(uname -r) ``` 该包提供路径如`/usr/src/linux-headers-$(uname -r)`,包含编译所需头文件、Makefile 和符号表[^3][^4]。 - 对于 RPM 系系统(如 CentOS),需安装`kernel-devel`包: ```bash yum install kernel-devel-$(uname -r) ``` #### **步骤 2:编写驱动 Makefile** 驱动编译需通过**内核构建系统**完成。典型的 Makefile 应包含以下内容: ```makefile KERNELDIR ?= /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) obj-m += your_driver.o all: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean ``` - `KERNELDIR`指向内核头文件目录(通常为`/lib/modules/$(uname -r)/build`的符号链接) - `M=$(PWD)`指定驱动源码的路径[^1][^5] - `obj-m`定义要编译模块对象文件 #### **步骤 3:处理头文件包含** 在驱动代码中引用内核头文件时: ```c #include <linux/module.h> // 内核模块基础头文件 #include <linux/fs.h> // 文件操作相关结构体 #include <linux/device.h> // 设备类注册功能 ``` - **不要使用绝对路径**,应通过内核构建系统自动解析路径 - 自定义头文件建议放在驱动源码目录,通过`LDDINCDIR`等参数传递路径 #### **常见问题排查** | 问题现象 | 解决方案 | |--------------------------|--------------------------------------------------------------------------| | "fatal error: linux/module.h: No such file" | 检查内核头文件是否安装,确认`KERNELDIR`路径是否正确 | | 版本不匹配警告 | 运行`uname -r`确认当前内核版本,重新安装对应版本头文件[^2] | | 交叉编译失败 | 设置`ARCH`和`CROSS_COMPILE`环境变量,如`export ARCH=arm64` | #### **示例:完整编译流程** ```bash # 查看当前内核版本 uname -r # 输出示例:5.4.0-80-generic # 安装对应头文件 sudo apt-get install linux-headers-5.4.0-80-generic # 编写驱动和Makefile后编译 make -C /lib/modules/$(uname -r)/build M=$(pwd) modules ``` 该过程通过内核构建系统自动处理: 1. 头文件搜索路径 2. 编译器标志(如`-DDEBUG`) 3. 模块签名验证(需配置CONFIG_MODULE_SIG)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值