本文旨在为想要深入Linux内核驱动开发的朋友,提供一份基于Linux 6.1.161内核版本的完整开发环境搭建与编译实操指南。通过从内核源码编译到外部驱动模块编译与加载的全流程,帮助你为后续的内核驱动源码走读和驱动开发调试做好准备。
编译环境说明
- 操作系统:Ubuntu 18.04
- 内核版本:6.1.161
- 目的:为后续驱动源码分析和驱动开发调试准备环境,因此操作主要集中在编译步骤,不包括内核的实际替换和启动。
环境依赖库安装
在进行任何编译工作之前,首先需要安装必要的编译工具和开发库。在终端中执行以下命令:
sudo apt-get update
sudo apt-get install -y build-essential flex bison libssl-dev libelf-dev \
ncurses-dev bc ca-certificates wget git gcc make dpkg-dev fakeroot \
rsync kmod cpio libncurses5-dev
一、下载内核源码
从官方镜像站下载指定版本的内核源码包,并解压到当前目录。
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.161.tar.xz
tar -xf linux-6.1.161.tar.xz
cd linux-6.1.161
二、配置内核
内核配置决定了哪些功能和驱动会被编译进内核,或者编译为模块。对于驱动开发和源码分析,开启必要的调试信息至关重要。
1. 配置内核基础配置
可以基于当前运行系统的配置生成一个基础配置文件。
cp /boot/config-$(uname -r) .config
或者,也可以使用内核默认配置:
make defconfig
2. 编辑内核配置(开启调试选项)
运行文本图形化配置界面,开启所有调试相关的选项,这将极大地方便后续的代码走读和问题追踪。
make menuconfig
进入配置界面后,导航到 Kernel hacking 菜单,尽可能勾选所有调试相关的选项。
请确保以下关键调试选项处于开启状态(=y):
CONFIG_DEBUG_INFO=y # 包含调试信息
CONFIG_DEBUG_INFO_DWARF5=y # DWARF5格式(GDB支持更好)
CONFIG_GDB_SCRIPTS=y # GDB脚本支持
CONFIG_KGDB=y # KGDB内核调试
CONFIG_FRAME_POINTER=y # 帧指针(backtrace)
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_DRIVER=y
CONFIG_DYNAMIC_DEBUG=y # 动态调试
如果需要编译特定的驱动(例如下文提到的null驱动或USB存储驱动),也需要在配置界面中开启相应的选项。下图展示了在 make menuconfig 中配置USB驱动模块的界面示例:

配置完成后,选择保存,配置文件将写入当前目录的 .config 文件中。
三、编译内核
完成配置后,就可以开始编译了。整个过程耗时较长,请耐心等待。
1. 编译内核镜像
使用 V=1 参数可以输出详细的编译过程,首次编译时推荐使用,便于观察进度和排查问题。-j$(nproc) 参数表示使用所有CPU核心并行编译以加快速度。
make V=1 -j$(nproc) //详细输出,首次编译时推荐查看编译过程
说明:编译过程中可能会提示证书相关的问题,可以通过创建一个空证书文件来规避此错误。
mkdir -p debian
touch debian/canonical-certs.pem
echo “” > debian/canonical-certs.pem
# 告诉系统使用空证书
scripts/config --set-str CONFIG_SYSTEM_TRUSTED_KEYS “”
2. 编译内核模块(驱动)
编译所有配置为模块(=m)的驱动和组件。
make modules -j$(nproc)
3. 安装内核模块
将编译好的模块安装到系统模块目录(例如 /lib/modules/6.1.161/)。
sudo make modules_install
4. 安装内核(可选)
此步骤会将编译好的内核镜像和System.map等文件安装到 /boot 目录,并更新引导配置。由于我们本次的目的主要是为了驱动开发和源码走读,并不一定需要替换当前运行的内核,因此此步可以省略。
# 安装内核到/boot
sudo make install
四、编译外部驱动模块
掌握了内核的编译方法后,我们来看看如何编译一个独立于内核源码树的外部驱动模块。这是开发者编写和调试自己驱动程序的常用方式。
1. 创建 hello.ko 驱动示例
首先,在一个独立目录下(例如 /path/to/hello_drv)创建最简单的 hello.c 驱动源文件。
#hello.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“My Name”);
MODULE_DESCRIPTION(“Hello World driver”);
static int __init hello_init(void)
{
printk(KERN_INFO “Hello world, kernel 6.1.161!\n”);
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO “Goodbye, kernel!\n”);
}
module_init(hello_init);
module_exit(hello_exit);
2. 创建 Makefile
在该目录下创建 Makefile 文件,其核心是指向之前编译好的内核源码目录。
#Makefile
KDIR ?=../linux-6.1.161
PWD := $(shell pwd)
# 指向你的内核源码目录
# KDIR ?= /path/to/linux-6.1.161
obj-m += hello.o
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
3. 编译驱动
在该目录下直接执行 make 命令,系统会自动调用内核源码树中的编译系统来编译你的驱动模块。
make
下图展示了执行编译命令和检查模块的部分终端输出:

编译成功后,会在当前目录生成 hello.ko 文件。之后,你可以使用 sudo insmod hello.ko 加载模块,使用 sudo rmmod hello 卸载模块,并通过 dmesg 命令查看驱动输出的日志信息,从而完成一个完整的外部驱动模块开发调试流程。
由于我们在编译内核时打开了详细输出,整个内核编译过程耗时较长。完成编译后,就可以利用这个搭建好的环境,深入内核源码世界,进行驱动代码的走读和开发实践了。希望这份指南能为你打开Linux内核驱动开发的大门,更多深入的技术文档和社区讨论,也可以在云栈社区找到相关的资源与交流。