前言
本文基本适用于所有发行版的脱离包管理器控制的内核编译安装,你可以通过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
像上部分的操作一样。