升级Linux内核是一个有一定风险的操作,不过如果操作系统的内核太老了,也可能导致部分新的应用程序无法运行,此外升级内核也可能能够提升一些性能等。
下面将以Debian发行版为例,讲解两种 升级内核的方法,即使用包管理器和手动编译,大家根据情况选择其一即可。
1,基于包管理器升级
使用包管理器升级内核是推荐的方法,我们可以通过下列命令搜索查看可安装的内核版本:
bash
apt list | grep linux-image
结果如下:
可见内核软件包的命名规则为:
arduino
linux-image-版本号-类型-架构
有的内核软件包没有"类型"这一部分例如linux-image-6.1.0-11-amd64
,说明是通用的内核,我们一般安装这种即可,对于有类型部分的包名,类型通常如下:
rt
对实时性应用程序优化的内核,提供更快的响应时间lowlatency
针对低延迟应用程序优化的内核cloud
适用于云计算的内核server
适用于服务器的内核generic
等同于没有类型的内核,即通用内核
事实上,不同类型内核一般是配置不同,实质是一样的。
此外,往下翻我们还能发现版本号带有+bpo
字样的内核包:
通常遵循下列命名方式:
arduino
linux-image-版本号+bpo-类型-架构
这种内核通常更新,但是稳定性可能不佳,来自于backports
软件源。
知道了软件包及其版本,我们直接使用apt
安装就可以完成内核升级工作,例如:
bash
sudo apt install linux-image-6.1.0-31-rt-amd64
sudo apt autopurge
sudo apt clean
重启系统,在grub
引导界面选择新安装的内核版本的选项即可:
启动后执行uname -r
命令可查看内核版本,确定是否更新成功。
带有
dbg
等其它后缀的软件包通常是包含调试符号、用于内核驱动开发的内核,这里我们先不关注。
2,源码编译安装
大多数情况下,不建议使用源码编译安装的方式升级内核,因为官方的内核通常比较新,我们现有的发行版不一定适配得很好,且绝大多数闭源驱动(例如NVIDIA、AMD显卡驱动)很可能会与最新内核不兼容,导致内核安装失败。
不过,如果你有一些定制化的需求,比如需要自定义内核编译配置等,或者单纯需要更加新的内核,则可以进行源码编译安装的方式。
(1) 下载源码包
进入Linux内核源码官方网站:传送门
选择stable
或者longterm
版本,点击对应版本右侧的tarball
链接下载:
例如下载后得到linux-6.13.3.tar.xz
文件,进行解压,解压后将得到linux-6.13.3
文件夹,进入源码文件夹:
bash
tar -xvf linux-6.13.3.tar.xz
cd linux-6.13.3
内核目录中文件如下:
(2) 安装依赖
编译内核需要安装一些基本依赖工具,执行下列命令:
bash
sudo apt install flex bison bc build-essential libssl-dev libelf-dev libncurses-dev
(3) 配置内核
如果你只是单纯的升级内核,我们可以将现有的内核配置复制过来,保持当前配置即可:
bash
cp /boot/config-$(uname -r) .config
yes '' | make oldconfig
反之,如果你对内核配置比较熟悉,且需要自定义一些配置,则可以执行下列命令进入配置界面:
bash
make menuconfig
或者,也可以使用下列命令生成一个通用默认配置:
bash
make defconfig
最终,出现configuration written to .config
说明已完成配置:
(4) 编译安装
有两种编译安装的方式:
- 直接编译源码并安装至系统
- 编译源码并打包为
deb
安装包,然后使用包管理器安装
这里将分别介绍这两种方式,大家根据喜好选其一即可。
① 直接编译安装
在源码目录中,执行下列命令完成编译安装:
bash
# 编译源码
make -j$(nproc)
# 安装内核模块
sudo make modules_install
# 安装内核
sudo make install
make
的-j
参数表示指定多线程编译,nproc
命令是用于输出当前处理器核心数的,这里指定给了-j
,也可以指定为固定线程数例如-j8
表示使用8
线程编译。
编译内核通常耗费的时间很长,以R5 7600X处理器为例,使用12
线程编译完成大概需要35
分钟左右。
如果编译失败或者中断,想要重新编译,则执行下列命令清理已编译结果:
bash
make mrproper
清理完成后,需要重新配置内核,再进行编译步骤。
② 编译打包为deb
再安装
内核源码也支持一键打包为deb
包,然后使用包管理器安装,这种方式比较推荐,因为后续我们可以统一使用包管理器管理多个版本内核。
要打包为deb
,我们还需要安装一些额外工具,执行下列命令:
bash
sudo apt install git rsync debhelper
然后在内核源码目录下,我们需要先创建一个git
仓库,否则无法进行后续打包工作:
bash
git init
git add .
git commit -m "message"
提交信息可以随意编写,若commit
失败则可能是没有配置提交人信息导致,执行下列命令:
bash
# 配置提交人信息
git config --global user.name "username"
git config --global user.email "[email protected]"
然后就可以开始编译构建工作了:
bash
make deb-pkg -j$(nproc) LOCALVERSION=''
这里使用deb-pkg
表示编译构建为安装包,此外还设定了变量LOCALVERSION
,该变量用于设定编译后内核版本号后缀,例如你设定LOCALVERSION=-custom
,那么编译后得到的内核版本号就是6.13.3-custom
,由于默认情况下构建deb
安装包时,版本号会有一个后缀+
,因此这里出于"强迫症"就设定版本号后缀为空字符串''
了,确保版本号是干净的。
编译完成后,deb
安装包会生成在上一级目录下,通过下列命令查看:
bash
ls ../ | grep '.deb$'
结果如下:
可见有4
个安装包,它们分别是:
linux-image-6.13.3_xxx_amd64.deb
内核镜像包,包含了编译好的内核和内核模块,这个包就是我们要安装的实际内核linux-headers-6.13.3_xxx_amd64.deb
内核头文件包,包含了编译内核模块所需的头文件,开发者在编写或编译内核模块时需要这个包linux-image-6.13.3-dbg_xxx_amd64.deb
内核调试信息包,包含了调试内核所需的符号和调试信息linux-libc-dev_xxx_amd64.deb
内核C库开发包,提供了用户空间程序在与内核交互时所需的头文件和库函数
一般来说,我们只需要安装linux-image-6.13.3_xxx_amd64.deb
内核镜像即可,使用dpkg -i
进行安装:
bash
sudo dpkg -i linux-image-6.13.3_6.13.3-g6e078ce39376-1_amd64.deb
如果需要安装或者编译驱动,则通常还需要安装linux-headers-6.13.3_xxx_amd64.deb
这个内核头文件包。
到此,内核升级完成,重启系统并执行命令uname -r
即可查看当前内核版本:
3,移除不要的内核
如果安装了很多内核,通常可以移除一部分,不过建议除了最新的内核之外,还是保留一个稳定版本的内核,防止启动失败。
(1) 包管理器安装的内核移除
对于包管理器安装的内核,我们直接卸载即可,执行下列命令查看我们安装了哪些版本的内核:
bash
# 列出已安装内核镜像
apt list --installed | grep linux-image
# 此外,还可以列出已安装的内核头文件包
apt list --installed | grep linux-headers
结果:
使用sudo apt purge
卸载你需要移除的内核即可。
(2) 手动安装的内核移除
如果说是使用make install
手动安装的内核,那么就稍微麻烦一点了,因为手动安装的内核是不会显示在apt list
里面的,就要手动删除。
我们可以先来了解一下内核相关文件存放位置,在手动安装时,内核文件安装在下列位置:
/boot
目录下:存放的是内核镜像等和启动相关内核文件,执行make install
时会将相关文件安装到该目录下/lib/modules
目录下:内核模块,通常是驱动以及其它系统相关模块,执行make modules_install
时会将相关文件安装到该目录下
首先查看/boot
目录如下:
可见一个版本的内核对应了多个相关文件,以6.13.3
版本为例:
config-6.13.3
内核编译时的配置文件,它包含了在编译过程中使用的各种选项和参数设置initrd.img-6.13.3
initrd(initial RAM disk)是一个临时磁盘镜像,它包含了必要的驱动程序和工具,用于在系统启动过程中挂载真正的根文件系统System.map-6.13.3
存放了编译内核时定义的内核函数和它们的内存地址之间的关系表vmlinuz-6.13.3
经过编译的内核的可执行映像文件,在Linux系统启动过程中,这个文件会被加载到内存中并由内核第一阶段程序解压和运行
删除对应版本的内核文件即可,例如:
bash
# 删除6.12.9+bpo-rt-amd64版本内核文件
sudo rm /boot/config-6.12.9+bpo-rt-amd64 /boot/initrd.img-6.12.9+bpo-rt-amd64 /boot/System.map-6.12.9+bpo-rt-amd64 /boot/vmlinuz-6.12.9+bpo-rt-amd64
然后查看/lib/modules
目录:
可见一个内核版本对应的模块文件,都以一个文件夹形式存放在该目录下,删除对应版本即可,例如:
bash
# 删除6.12.9+bpo-rt-amd64版本内核模块文件
sudo rm -rf /lib/modules/6.12.9+bpo-rt-amd64
此外,我们发现根目录下还有符号链接:
这些符号链接指向了当前实际使用的内核文件,但如果删除了其指向就不存在了,我们删除链接,然后重新创建:
bash
# 删除链接
sudo rm /initrd.img /initrd.img.old /vmlinuz /vmlinuz.old
# 重新链接至新内核
sudo ln -s /boot/initrd.img-6.13.3 /initrd.img
sudo ln -s /boot/vmlinuz-6.13.3 /vmlinuz
最后重新生成镜像并更新GRUB引导即可:
bash
sudo update-initramfs -u
sudo update-grub
到此,内核的升级以及旧版本清理工作完成,在实际情况下需要谨慎升级内核。