Linux内核编译基本流程
LinuxUser001作
注:阅读这篇文章可能需要一定的Linux经验/了解编译原理
内核源代码下载和解压
下载
Linux内核源码可以去官网下载,当然,BFSU也提供了它的镜像源,现在写这篇文章的机器用的是目前的最新版本6.0-rc7(直链下载,点开就是)。
解压
$ tar xpvf linux-xxx.tar.gz
当它跑完一堆信息之后,你会发现工作目录多了一个linux-xxx
目录,这就是它释放出来的源码
配置
menuconfig
在我们cd进目录之后,运行
$ make menuconfig
它会编译少量用于TUI界面的源码并且运行,之后我们就会进入一个

这样的界面,我们可以用回车键进入子项目,用空格键修改条目的状态比如模块模式、常驻模式或者禁用,也可以写入字符串,选择它提供的其他模式
xconfig
当然,如果menuconfig的界面太复杂,内核也提供了基于qt的前端配置软件,我们只需要输入
$ make xconfig
就可以得到一个

这样的界面
gconfig(不推荐使用)
因为这个需要的依赖太多了(指haskell全家桶),我就不演示了
$ make gconfig
编译
源码编译
经过上述操作之后,我们的源码目录会多出来一个.config
文件,当然,如果懒人也可以套一个现在正在工作的配置再进行少量的修改,同样能达到和原来的内核几乎无缝衔接的体验
最后,我们准备泡一杯茶,然后运行
$ make -j$(nproc)
静静等待,大约半个小时后,我们就可以进入下一步
此时Linux内核文件正是./arch/$(uname -m)/boot/bzImage
模块安装
当然,如果我们直接拿上一步的产物去启动,那么恭喜你得到了一个内核恐慌
因为这个时候的内核没有初始化内存盘和移动模块,也就是说内核加载不到任何驱动
于是
$ sudo make modules_install
可以把编译的模块全部送进/lib/modules/$(uname -r)/
目录让内核识别
之后,我们还要给内核生成一个内存盘
$ sudo mkinitcpio -k $(uname -r) -g /boot/initramfs-$(uname -r).img
这个时候就基本搞定内核的编译了
后续的处理
私有驱动模块
这就是我们目前最棘手的问题,一些臭名昭著的外部模块比如某伟达的驱动,这样我们就分成两种情况来
之前没有安装过驱动的
在这种情况下还是很好处理的,我们直接安装对应的软件包即可
之前安装过驱动的
在这种情况下,我们就需要进行
graph LR
rebuild(重新编译) ---> insmod(导入模块) ---> depmod(评估模块依赖性) ---> genmemdisk(生成内存盘)
的麻烦操作
首先,我们要先进入/usr/src
目录,一般私有驱动的源码会放在这里面
接着,我们要运行
$ sudo make clean
清除之前的中间文件,然后开始编译
$ sudo make -j$(nproc)
编译完成后,生成的*.ko
文件就是兼容当前内核的模块,我们需要将模块复制/移动进/usr/lib/modules/$(uname -r)/kernel/
里面的任何地方(建议根据模块功能类型做好分类,不分类也不会影响下一步),然后执行
$ sudo depmod -v $(uname -r) -A -a
进行模块依赖性评估,并且生成modprobe命令可以读取的modules.dep等一系列文件,最后再重启,我们就可以使用这些模块了
—
当然,如果是一些“正规的”大项目提供的私有驱动,它们就会提供modules_install
的make选项来自动完成操作
这篇文章篇幅很短,让我们知道编译Linux内核并不难