为什么要编译内核

因为驱动运行在内核态,如果我们需要debug驱动的代码的话,就需要下内核断点,而内核断点需要带调试信息的kernel,所以我们需要自己编译内核。
因为在ubuntu 20.04下,自带的kernel开启了内核驱动签名的保护机制,导致我们编译的驱动并不能加载到kernel中,所以需要更改内核的相关配置参数,关闭kernel的驱动签名机制

Step1:下载内核

内核的下载地址:https://www.kernel.org/
最好选择当前系统内核的同大版本的内核,比如20.04的内核是5.15.xx,最好选择5.15下面的内核,大版本不同的内核可能会出现错误
这里选用5.15.63的内核
下载内核后执行:unxz -v linux-5.15.63.tar.xz
在解压完成之后,就可以在目录下看到linux的源代码:
image.png

Step2:安装构建内核的依赖

执行如下的语句,安装内核的依赖:sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison
在linux官方文档下也提供了编译linux所需要安装的工具包:https://docs.kernel.org/process/changes.html#changes

Step3:关闭内核驱动签名

执行make menuconfig可以设置内核的一些配置,我们自己编译的内核重点要关注两个配置:

  1. 开启内核的调试模式,也就是让kernel带上debug信息
  2. 关闭内核的驱动签名保护
    执行成功后,可以看到如下的界面:
    image.png
    首先开启内核调试,选择kernel hacking -> Compile-time checks and compiler options -> Compile the kernel with debug info,开启这个配置
    image.png

之后我们需要关闭内核驱动签名,但是这个选项在menuconfig里面没法变更,我们需要在.config文件中手动配置
image.png
用vim打开.config文件,并将里面的CONFIG_MODULE_SIG选项更改为n
image.png

Step4:编译kernel

当把所有的kernel配置更改完了以后,就可以执行make命令构建kernel,kernel构建的时间比较长,而且编译过程中可能会遇到一些包缺失的情况,一般都可以通过apt安装对应的包即可解决问题

执行如下命令:make -j8开始kernel的编译
当编译结束后,需要安装内核驱动到对应的目录,执行make module_install将内核驱动安装到系统的位置

最后一步执行make install将安装内核到系统中,并且将内核切换为当前编译的内核,重新启动,执行uname -r即可看到内核的版本
image.png

Step5:验证驱动签名关闭

按照第一篇的内容构建一个hello world的驱动模块,但是按照之前的makefile无法成功构建模块(可能是因为之前是arch系统),使用如下的makefile:

KVERSION = $(shell uname -r)
KERN_DIR =  /lib/modules/$(KVERSION)/build 
all:
	CONFIG_MODULE_SIG=n make -C $(KERN_DIR) M=`pwd` modules 
clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order
obj-m	+= helloworld.o

即可成功编译出helloworld.ko文件,之后执行insmodrmmod均未发现报错,且dmesg成功输出:
image.png