the site subtitle

如何为CentOS7升级4.x内核

2021.03.07

默认的CentOS 7 使用的是 3.x版本的内核,比如 7.3使用的是3.10.0-957.5.1.el7.x86_64,大版本号也就是3.10.0,后面的957也就是不断的维护的小版本,如果你不升级的话,仅仅是update的话,只会增加最后的小版本号。但是当我们想使用高版本内核才支持的特性的时候,就需要升级。打开https://www.kernel.org/ 你会发现有下面几个版本:那怎么才能找到需要的版本的包呢?

mainline: 5.13-rc1 2021-05-09
stable: 5.12.4 2021-05-14
stable: 5.11.21 2021-05-14
longterm: 5.10.37 2021-05-14
longterm: 5.4.119 2021-05-14
longterm: 4.19.190 2021-05-07
longterm: 4.14.232 2021-04-28
longterm: 4.9.268 2021-04-28
longterm: 4.4.268 2021-04-28
linux-next: next-20210514 2021-05-14

首先我们来看下最小化系统默认安装了哪些kernel相关的包:

# rpm -qa |grep kernel
kernel-3.10.0-957.5.1.el7.x86_64
kernel-tools-3.10.0-957.5.1.el7.x86_64
kernel-headers-3.10.0-957.21.3.el7.x86_64
kernel-tools-libs-3.10.0-957.5.1.el7.x86_64

rpm -ql kernel
/boot/symvers-3.10.0-957.5.1.el7.x86_64.gz
/boot/vmlinuz-3.10.0-957.5.1.el7.x86_64
/etc/ld.so.conf.d/kernel-3.10.0-957.5.1.el7.x86_64.conf
/etc/modprobe.d/dccp-blacklist.conf
/lib/modules/3.10.0-957.5.1.el7.x86_64

rpm -ql kernel-tools
/usr/bin/centrino-decode
/usr/bin/cpupower
/usr/bin/powernow-k8-decode
/usr/bin/tmon
/usr/bin/turbostat
# 这个是附带的kernel源码包,用于一些需要编译才能安装的包使用
rpm -ql rpm -ql kernel-headers
/usr/include/syscall.h

升级kernel

如何找到新版本的kernel rpm包? 从谷歌搜到elrepo.org一直维护着Centos kernel rpm,打开一个其中mirror http://mirrors.coreix.net/elrepo/kernel/el7/x86_64/RPMS/ ,你会发现只有两个版本的kernel???一个是lt,一个是ml?后来才发现lt就是长期维护的意思,而ml就是main line主线内核,可以理解为最新的稳定版。这里我选择的是lt版本的,下面也列出了安装命令。但是需要注意的是,这里的版本不是固定的,也就是过一段时间可能就是另一个更新的版本了。

# 这里是Centos 7 其他版本自行替换掉所有的7
yum install https://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm

cat /etc/yum.repos.d/elrepo.repo
[elrepo-kernel]
name=ELRepo.org Community Enterprise Linux Kernel Repository - el7
baseurl=http://elrepo.org/linux/kernel/el7/$basearch/
        http://mirrors.coreix.net/elrepo/kernel/el7/$basearch/
        http://mirror.rackspace.com/elrepo/kernel/el7/$basearch/
        http://repos.lax-noc.com/elrepo/kernel/el7/$basearch/
mirrorlist=http://mirrors.elrepo.org/mirrors-elrepo-kernel.el7
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-elrepo.org
protect=0

yum --enablerepo=elrepo-kernel install kernel-lt

升级其他kernel相关包 (可选)

其实做完上一步已经可以了,但是如果你需要编译其他的模块,那么最好安装一下kelnel-tool等其他包,因为系统中已经存在3.x的,所以会提醒依赖冲突,可以用下面的命令来解决。

yum --enablerepo=elrepo-kernel install kernel-lt-headers -y
Resolving Dependencies
--> Running transaction check
---> Package kernel-lt-headers.x86_64 0:4.4.190-1.el7.elrepo will be installed
--> Processing Conflict: kernel-lt-headers-4.4.190-1.el7.elrepo.x86_64 conflicts kernel-headers < 4.4.190-1.el7.elrepo
--> Restarting Dependency Resolution with new changes.
--> Running transaction check
---> Package kernel-headers.x86_64 0:3.10.0-957.21.3.el7 will be updated
---> Package kernel-headers.x86_64 0:3.10.0-957.27.2.el7 will be an update
--> Processing Conflict: kernel-lt-headers-4.4.190-1.el7.elrepo.x86_64 conflicts kernel-headers < 4.4.190-1.el7.elrepo
--> Finished Dependency Resolution
Error: kernel-lt-headers conflicts with kernel-headers-3.10.0-957.27.2.el7.x86_64
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest
 
# 替换系统默认的
yum --enablerepo=elrepo-kernel -y swap kernel-headers -- kernel-lt-headers
yum --enablerepo=elrepo-kernel -y swap kernel-tools-libs -- kernel-lt-tools-libs
yum --enablerepo=elrepo-kernel -y install kernel-lt-tools
yum --enablerepo=elrepo-kernel -y swap kernel-devel -- kernel-lt-devel

更改Grub

安装新内核之后默认其实还是从旧内核启动,所以这一步也是很重要的。可以编辑/etc/default/grub,加入一下配置并保存。

GRUB_DEFAULT=0
# 这一步没有测试,仅作备忘
grub2-mkconfig -o /boot/grub2/grub.cfg

grub2-set-default 0

编译内核

如果对默认内核的参数需要修改么办?自己编译!当然这也需要一些基础知识。如果已经安装了kernel-devel包,就可以在/usr/src/kernels/这个目录找到对应的Kernel源码,编译需要一些依赖包,如下所示:

yum install -y ncurses-devel make gcc bc bison flex elfutils-libelf-devel openssl-devel grub2
# 然后就可以进入TUI编译了
# 这一步默认会生成.config文件,编译参数都是从这个文件读取的,可以先把默认的保存下来
make menuconfg

make bzImage
make modules
make
make install
make modules_install

.config 文件内容

#
# Automatically generated file; DO NOT EDIT.
# Linux/x86_64 4.4.190-1.el7.elrepo.x86_64 Kernel Configuration
#
CONFIG_64BIT=y
CONFIG_X86_64=y
CONFIG_X86=y
CONFIG_INSTRUCTION_DECODER=y

以上的只能作为自己的测试使用,现实情况更多的还是分发编译好的rpm。可以从https://www.kernel.org/直接下载对应版本的压缩包,解压后使用make rpm-pkg进行编译,这时你发现编译出来的rpm太大了,有几百M,可以看这里https://winddoing.github.io/post/cb2d9d77.html ,使用make INSTALL_MOD_STRIP=1 rpm-pkg,而且会有会有一些并不需要的内核模块,进一步增加了体积。最终的结果还有会有100多M的,这个方法属于Linux开发者使用的,对于Centos更长用的还是自己写rpm的spec文件,也就是构建构建声明,然后用rpmbuild来构建。

还记得我们之前提到的elrepo么,以4.19.170为例,我是先找到elrepo在4.19-ml的srpm,只有spec等文件,Centos推荐专门创建一个用户用户构建rpm,避免直接使用root用户。以我下载的kernel-ml-4.19.9-1.el7.elrepo.nosrc.rpm为例,

首先 rpm -ivh kernel-ml-4.19.9-1.el7.elrepo.nosrc.rpm会在~/rpmbuild/生成相应的目录结构,~/rpmbuild/BUILD/kernel-*/linux-*/这个目录默认是没有.config文件的,需要你从现在系统的/boot/目录拷贝过来,当然也可以用make menuconfig自己配置,如果使用就的config文件在构建的时候有一些的新的参数会让你手动选择的。

然后在~/rpmbuild/SPEC执行

rpmbuild -bb –target=uname -m kernel.spec命令,就会开始构建

除此以外4.x版本的内核推荐使用gcc9作为编译工具链,不出问题的话就会得到你需要的rpm文件。

测试内核

这里就要用到qemu,神器!!!可以在虚拟机上运行,甚至可以模拟arm,一般来说需要自己打包rootfs,或者是用busybox,我这里偷懒,直接使用Ubuntu的。https://cloud-images.ubuntu.com/

sudo qemu-system-x86_64 \
-m 2G -smp 2 \
-hda qemu-image.img  \
-kernel linux-5.4-rc4/arch/x86/boot/bzImage \
-append "debug root=/dev/sda  console=ttyS0" \
-nographic 
# 支持kvm的话加上 -enable-kvm \

但是可惜的是无法启动,各种panic,或者就是文件系统挂载出问题,心一横直接安装在vm上面,结果根本没有问题

Ref

Kernel

http://elrepo.org/tiki/tiki-index.php

How to install kernel 4.x on CentOS 7.x

https://qiita.com/tkprof/items/2ec4ed58790efba3778d

Linux Kernel 编译踩坑 - o0xmuhe’s blog https://o0xmuhe.github.io/2019/10/24/Linux-Kernel-%E7%BC%96%E8%AF%91%E8%B8%A9%E5%9D%91/