编译第一个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. 总结流程
- 安装内核头文件和编译工具
- 编写 Makefile,指定头文件路径
- make 编译
- insmod 加载测试
—
ARM-LINUX交叉编译
在 Linux 系统中,安装与当前运行内核版本匹配的开发包(通常是 linux-headers
或 kernel-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) 开发包版本与内核不匹配
- 原因:系统更新了内核但未重启,或仓库中缺少对应版本。
解决步骤:
检查可用开发包版本:
# Ubuntu/Debian apt list linux-headers-* # RHEL/CentOS dnf list kernel-devel-*
- 安装匹配版本或重启系统以加载新内核:
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
Makefile
、include
等目录。
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-headers
或kernel-devel
。 - 关键路径:
/lib/modules/$(uname -r)/build
(编译模块时KERNELDIR
的默认路径)。/usr/src/linux-headers-$(uname -r)
(头文件实际位置)。
- 强制建议:始终保持内核版本与开发包版本一致!