Linux驱动测试示例
+ -

编译第一个LINUX驱动

2025-07-22 14 0

已经有了字符驱动的源代码,并且准备在 PC 的 Ubuntu 22.04 上编译。下面详细说明除了指定 Linux 源代码路径外,还需要做哪些环境配置和注意事项,确保你能顺利编译出内核模块(驱动)。


1. 内核源码的选择与准备

  • 推荐使用与你当前运行内核版本一致的内核源码或头文件,否则编译出的模块可能无法被当前内核加载。
  • 无需下载完整内核源码,只要有对应内核的“内核头文件(kernel headers)”即可。

查看当前内核版本

uname -r

例如输出:5.15.0-60-generic


2. 安装内核头文件和编译工具

在 Ubuntu 上,直接安装内核头文件和构建工具即可:

sudo apt update
sudo apt install build-essential linux-headers-$(uname -r)
  • build-essential 包含 gcc、make 等编译工具。
  • linux-headers-$(uname -r) 安装与你当前内核版本匹配的头文件。

3. Makefile 的基本写法

假设你的驱动源文件叫 mychardev.c,Makefile 可以这样写:

obj-m += mychardev.o
all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  • /lib/modules/$(uname -r)/build 是当前内核的头文件和Makefile所在目录,Ubuntu自动维护。
  • obj-m 表示要编译成模块的对象文件。

4. 编译驱动模块

在驱动源代码目录下执行:

make

编译成功后会生成 mychardev.ko 文件,这就是你的内核模块。
编译输出:

[root@mypcie mytest]# ll
total 436
-rw-r--r-- 1 root root    160 Jul 22 20:40 Makefile
-rw-r--r-- 1 root root     28 Jul 22 20:47 modules.order
-rw-r--r-- 1 root root      0 Jul 22 20:47 Module.symvers
-rw-r--r-- 1 root root    280 Jul 22 20:47 mychardev.c
-rw-r--r-- 1 root root 210744 Jul 22 20:47 mychardev.ko
-rw-r--r-- 1 root root    826 Jul 22 20:47 mychardev.mod.c
-rw-r--r-- 1 root root 108984 Jul 22 20:47 mychardev.mod.o
-rw-r--r-- 1 root root 103200 Jul 22 20:47 mychardev.o

5. 加载和测试模块

  • 加载模块
    sudo insmod mychardev.ko
    
  • 查看模块是否加载
    lsmod | grep mychardev
    
  • 查看内核日志(调试信息):
    dmesg | tail -n 20
    
  • 卸载模块
    sudo rmmod mychardev
    

6. 常见问题与注意事项

  • 内核版本要匹配:编译用的头文件必须和运行内核一致,否则模块可能无法加载。
  • 不建议直接用官网主线源码,除非你自己编译并运行了该内核。一般用 /lib/modules/$(uname -r)/build 下的头文件。
  • 如果要为其他内核版本编译,需要安装对应版本的 headers,并指定 -C 路径。
  • 开发环境建议:用虚拟机或容器环境,便于测试和还原。

7. 总结流程

  1. 安装内核头文件和编译工具
  2. 编写 Makefile,指定头文件路径
  3. make 编译
  4. insmod 加载测试

ARM-LINUX交叉编译

在 Linux 系统中,安装与当前运行内核版本匹配的开发包(通常是 linux-headerskernel-devel)是编译内核模块(如驱动程序)的前提。以下是不同发行版的安装方法:


1. 确认当前内核版本

在安装之前,先确认系统正在使用的内核版本:

uname -r

输出示例:

5.15.0-78-generic

2. 根据发行版安装开发包

(1) Debian/Ubuntu 及其衍生版

  • 开发包名称格式:linux-headers-$(uname -r)
  • 安装命令:
    sudo apt update
    sudo apt install linux-headers-$(uname -r)
    
  • 验证安装
    检查头文件路径是否存在:
    ls /usr/src/linux-headers-$(uname -r)
    

(2) RHEL/CentOS/Fedora

  • 开发包名称格式:kernel-devel-$(uname -r)
  • 安装命令:

    # RHEL/CentOS 8+
    sudo dnf install kernel-devel-$(uname -r)
    
    # CentOS 7
    sudo yum install kernel-devel-$(uname -r)
    
  • 验证安装
    rpm -qa | grep kernel-devel
    ls /usr/src/kernels/$(uname -r)
    

(3) Arch Linux

  • 开发包名称:linux-headers
  • 安装命令:
    sudo pacman -S linux-headers
    
    (默认安装最新内核的头文件,需确保运行内核与 pacman 版本一致)

(4) openSUSE

  • 开发包名称:kernel-devel
  • 安装命令:
    sudo zypper install kernel-devel
    

3. 特殊情况处理

(1) 开发包版本与内核不匹配

  • 原因:系统更新了内核但未重启,或仓库中缺少对应版本。
  • 解决步骤

    1. 检查可用开发包版本:

      # Ubuntu/Debian
      apt list linux-headers-*
      
      # RHEL/CentOS
      dnf list kernel-devel-*
      
    2. 安装匹配版本或重启系统以加载新内核:
      sudo reboot
      

(2) 自定义内核或第三方内核

  • 若使用自定义编译的内核,需手动确保:
    • 内核源码路径与 lib/modules/$(uname -r)/build 符号链接指向正确位置。
    • 开发包需从源码编译安装:
      cd /path/to/kernel/source
      make headers_install
      

      make headers_install 是 Linux 内核构建系统(Kbuild)提供的一个命令,用于将内核头文件安装到指定目录,供用户空间程序或外部模块编译使用.其原理是从内核源码中提取用户空间API相关的头文件(如 linux/fs.h, linux/net.h),并将其安装到目标目录(默认 usr/include)

安装到自定义目录:

sudo make headers_install INSTALL_HDR_PATH=/opt/kernel-headers

清理已经安装的头文件:

make headers_install INSTALL_HDR_PATH=/path/to/target clean

4. 验证开发包安装成功

  • 检查内核头文件路径是否存在:
    ls /lib/modules/$(uname -r)/build
    
    正常应包含 Makefileinclude 等目录。

5. 常见问题

问题:无法找到对应版本的开发包

  • 解决方案
    • 更新软件源:
      sudo apt update        # Debian/Ubuntu
      sudo dnf makecache    # RHEL/CentOS
      
    • 启用官方或第三方仓库(如 elrepo 对 CentOS)。

问题:符号链接 /lib/modules/$(uname -r)/build 损坏

  • 修复命令
    sudo ln -sf /usr/src/linux-headers-$(uname -r) /lib/modules/$(uname -r)/build
    

总结

  • 核心命令:根据发行版选择 apt/dnf/yum/pacman/zypper 安装 linux-headerskernel-devel
  • 关键路径
    • /lib/modules/$(uname -r)/build(编译模块时 KERNELDIR 的默认路径)。
    • /usr/src/linux-headers-$(uname -r)(头文件实际位置)。
  • 强制建议:始终保持内核版本与开发包版本一致!

0 篇笔记 写笔记

关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!