Gentoo Linux practice Notes: Linux Kernel compiling

前言

本文基本适用于所有发行版的脱离包管理器控制的内核编译安装,你可以通过git拉取仓库或者网站下载tar ball,但是更推荐使用包管理获取当前运行的内核的源代码,自己重新进行打包,或者手动编译内核。

在Gentoo Linux上,内核的编译占日常滚动的一大部分,编译出一个好用的内核,对Gentoo的整体表现至关重要。在main tree中,内核包的形式主要有三种,其中gentoo-kernel-bin不需要本地编译,可以用来快速安装一个Gentoo系统,不在本文的讨论范围之内。下面分别讨论通过手动与包管理的方式安装内核。

手动使用源码编译安装

手动使用源码编译安装,需要获得源码,然后配置内核,编译内核,并且手动编译树外模块。

获取源码

使用*-sources结尾的包名获取对应内核分支的源码,或者在https://kernel.org/上获取tar ball,你也可以使用git直接拉取想要编译的分支的仓库,但要记得加上--depth=1的选项,linux的git历史十分庞大,不需要拉取过多的历史commit记录。

  • {gentoo, xanmod}-sources

使用类似的包,会把对应的打过patch的内核源码放到/usr/src/linux-${PV}-${PN}/下。

  • tar ball

如果你打算使用这次编译的内核,请按照上面的位置与命名方式进行放置;如果你只是想简单的编译一下,不打算使用,推荐将其放置在内存中(例如/tmp),内核源码占用大约1G的空间,编译时则根据你的选项会占用不同的内存大小,这样不影响硬盘的寿命,并且会减少文件读写的时间。

  • git

使用git clone git@github.com:torvalds/linux.git --depth=1来获取最新的内核源码,但是这通常会有很多bug。

配置内核

进入内核源码目录下,使用make menuconfig进行TUI模式下的配置,这使用了ncurses来制作TUI,是大部分人都会推荐的配置方式。在XWindows下也可以使用Qt进行图形化的配置:make xconfig

可以使用默认的配置来编译一个可以使用的内核,但是通常内核的功能会有冗余,如果想精简内核,或者单纯想缩短内核编译的时间,可以在源码目录下使用make localyesconfig或者make localmodconfig。前者会尽可能将使用当前用的模块编译进内核二进制中,后者会尽可能将当前用到的模块选择成为内核模块,保留尽可能少的built-in模块。

此外,如果想使用LLVM的Clang来编译GNU的Linux kernel,需要设置LLVM_IAS=1 LLVM=1这两个环境变量进行配置,这样你可以较为安全地使用O3优化,并且可以对kernel进行LTO优化。

详细的内核配置可以看一下这一篇文章(WIP

编译与安装

使用make -jX来编译内核,X是当前CPU的线程数;如果使用了Clang来编译内核,你需要设置以下环境变量

export LLVM_IAS=1
export LLVM=1
export CC=clang
export LD=ld.lld
export AR=llvm-ar
export NM=llvm-nm
export OBJCOPY=llvm-objcopy
export OBJDUMP=llvm-objdump
export READELF=llvm-readelf
export STRIP=llvm-strip

这是一个非常完全的列表,Kbuild是支持使用LLVM=1这个变量来使用LLVM的套件来编译的。

最后需要编译树外模块,例如ZFS和Nvidia的驱动。

完全编译完成后,安装内核二进制文件与模块:

make install
make modules_install

更新 Boot loader

Grub不能自动发现新的内核,需要重新生成一下grub的配置。

# grub 选项的等待时间,设置成0则不等待选择
GRUB_TIMEOUT=1
# 内核启动选项,这时可以加入loglevel等级,删除quiet与splash这两个选项,日志等级从低到高内容越来越详细。
GRUB_CMDLINE_LINUX="loglevel=5"

Debian系的发行版有update-grub这个封装,可以直接来更新grub的配置,在其它发行版上则需要使用grub-mkconfig -o /boot/grub/grub.cfg,在某些保留了grub的老旧版本的老旧发行版上,需要使用grub2-mkconfig -o /boot/grub2/grub.cfg来更新。

重启使用新内核

进入grub引导界面后,按e编辑grub脚本,Ctrl+X来引导内核。

Portage编译安装内核

感谢dist-kernel项目让我们使用上了二进制内核包与portage自动编译的内核。

配置内核

进入main tree,使用ebuild *.ebuild prepare来获取准备好的内核源码,在/var/tmp/portage/${CATEGORY}/${P}/work/linux-${PV%.*}下,使用上面的配置命令来配置,获取.config文件,最后将其移动到并重命名为/etc/portage/savedconfig/${CATEGORY}/${P}。这样savedconfig的USE FLAG就可以使用到自己的配置了。

使用LLVM编译与配置的方式一样,设置配置时与portage构建时的环境变量即可。

更新树外模块

推荐使用dist-kernel这个USE,可以自动在内核更新的时候编译树外模块,但是重新emerge不会触发。

更新 Boot loader

像上部分的操作一样。

知识共享许可协议
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
上一篇
下一篇