源码编译内核-CentOS7上Linux内核的编译和升级

在CentOS7环境下遇到由于某种原因需要升级内核的场景,经过一番查找,在网上找到了一个可以直接使用的RPM,大大减轻了工作量,但我开始对如何编译产生了兴趣内核。 那么让我们来实验一下。

一些内核知识

Linux内核代号分为Prepatch、Mainline、Stable、LongTerm(LongTermSupport)等,其中:

前面提到,由于一定的激励,需要升级内核来解决问题。 经过仔细的代码比对,最终选择了5.15内核版本进行版本升级。 内核升级完成后,问题解决。

内核编译计划

编译环境

注意:编译过程中的输出非常大。 确保编译目录所在的c盘有足够的可用空间。 刚开始我的测试过程中,c盘只有25G可用空间,导致由于空间不足导致编译失败。 之前的扩容是20G。 只需要45G就可以保证编译顺利。

海湾合作委员会打算

CentOS7系统自带的GCC版本为4.8.5,不再满足5.15内核的编译条件。 这里我们使用SCL软件设置来使用更高版本的GCC:

$ sudo yum install -y centos-release-scl scl-utils-build$ sudo yum install -y devtoolset-9-toolchain

安装后,可以在当前会话中激活它:

$ scl enable devtoolset-9 bash$ gcc --version
gcc (GCC) 9.3.1 20200408 (Red Hat 9.3.1-2)Copyright (C) 2019 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

可以看到GCC版本已更改为GCC9.3.1,但请注意这些方法仅在当前会话中生效,当用户切换或打开新会话时需要重新激活。

RPM包管理工具

编译之前需要安装RPM包管理工具rpmdevtools:

sudo yum -y install rpmdevtools

rpmdev-setuptree命令可以在当前用户下手动创建rpmbuild目录,用于编译rpm包。 其结构如下:

[develop@localhost rpmbuild]$ tree.├── BUILD├── RPMS├── SOURCES├── SPECS└── SRPMS
5 directories, 0 files

编译方法一

1、安装依赖包:

$ sudo yum install -y gcc make ncurses-devel flex bison openssl-devel elfutils-libelf-devel perl bc

2.下载代码包:

$ wget https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.15.126.tar.xz

3.解压代码:

$ tar -xvf linux-5.15.126.tar.xz

4、将当前内核编译配置复制到新内核源码中,主要是设置内核编译选项。 复制当前用于启动系统的配置是最安全的形式。

$ cd linux-5.15.126$ cp /boot/config-$(uname -r) ./.config

如果需要以文本图形的形式配置内核并调整内核加载模块,可以执行以下操作:

General setup  —>Select Local version – append to kernel release

5.减小RPM包尺寸:

1)CONFIG_DEBUG_INFO:如果我们的内核中启用了CONFIG_DEBUG_INFO选项,那么我们编译出来的二进制补码代码就会带来很多调试信息。 内核镜像镜像全部被修剪和优化,而驱动则没有,所以单个KO的大小非常大。 为了减小 RPM 的大小,您需要编辑 .config 文件并注释以下行:

CONFIG_DEBUG_INFO=y
to
#CONFIG_DEBUG_INFO=y

2)INSTALL_MOD_STRIP:另一个重要的事情是编译时传递给make的参数INSTALL_MOD_STRIP。 如果设置了 INSTALL_MOD_STRIP,驱动程序将被剥离以减少输出的大小。 关于,内核kbuild文档中的描述是:

 INSTALL_MOD_STRIP  If this variable is specified, it will cause modules to be stripped  after they are installed.  If INSTALL_MOD_STRIP is '1', then thedefault option --strip-debug will be used.  Otherwise, the  INSTALL_MOD_STRIP value will be used as the option(s) to the strip  command.

这里你可能会问,什么是strip? Strip是通过删除可执行文件中ELF头的typchk段、符号表、字符串表、行号信息、调试段、注释段、重定位信息等来减少程序体积。 的目标。 在内核编译测试中,不使用INSTALL_MOD_STRIP制作的kernel-5.15.126RPM包大小近1G,设置后大小只有几十兆,非常有效。

6、这里先暂停一下,先看一下内核makefile通过makehelp提供的功能,有很多,我们看几个比较常用的:

Cleaning targets:  clean      - Remove most generated files but keep the config and                    enough build support to build external modules  mrproper    - Remove all generated files + config + various backup files  distclean    - mrproper + remove editor backup and patch files
Configuration targets: menuconfig - Update current config utilising a menu based program
Kernel packaging: rpm-pkg - Build both source and binary RPM kernel packages binrpm-pkg - Build only the binary kernel RPM package deb-pkg - Build both source and binary deb kernel packages bindeb-pkg - Build only the binary kernel deb package

在:

7、编译并执行:

$ sh -c 'yes "" | make INSTALL_MOD_STRIP=1 rpm-pkg -j 16'

make执行后会有一堆确认项,可以通过“yes”手动处理。

在我的机器上编译一次大约需要一个小时。 当看到如下内容时,说明编译成功:

Wrote: /home/develop/rpmbuild/SRPMS/kernel-5.15.126-1.src.rpmWrote: /home/develop/rpmbuild/RPMS/x86_64/kernel-5.15.126-1.x86_64.rpmWrote: /home/develop/rpmbuild/RPMS/x86_64/kernel-headers-5.15.126-1.x86_64.rpmWrote: /home/develop/rpmbuild/RPMS/x86_64/kernel-devel-5.15.126-1.x86_64.rpmExecuting(%clean): /bin/sh -e /var/tmp/rpm-tmp.1Vmnnr+ umask 022+ cd /home/develop/rpmbuild/BUILD+ cd kernel-5.15.126+ rm -rf /home/develop/rpmbuild/BUILDROOT/kernel-5.15.126-1.x86_64+ exit 0

此时在rpmbuild/RPMS/x86_64目录下可以看到编译完成的三个RPM:

total 232212-rw-rw-r-- 1 develop develop  67109724 Aug 12 01:04 kernel-5.15.126-1.x86_64.rpm-rw-rw-r-- 1 develop develop   1464848 Aug 12 01:04 kernel-headers-5.15.126-1.x86_64.rpm-rw-rw-r-- 1 develop develop 169205676 Aug 12 01:05 kernel-devel-5.15.126-1.x86_64.rpm

这里编译完成后的RPM可以进行升级和测试。 我们来谈谈升级后的测试。

编译方法二

ELRepo项目

常见的内核升级方案中,比较常见的方法之一是使用ELRepoProject提供的内核版本,同时ELRepoProject将内核名称更改为kernel-ml以避免与RHEL内核冲突。 其kernel-ml依然提供了最新版本内核的rpm安装包。 但新大版本发布后,将不再提供旧版本。 您可以在各种镜像站点上看到它。 目前提供kernel-ml-6.4.9和kernel-ml-6.4.8的RPM包。

需要5.15LTS版本来解决这个问题,那么如何编译5.15版本的kernel-ml包呢?

经查资料,kernel-ml分支在5.15到5.15.13之后不再更新。 幸运的是,我找到了5.15.13 SRPM包kernel-ml-5.15.13-1.el7.elrepo.nosrc.rpm。

SRPM

什么是 SRPM?

SRPM包比RPM包多了一个“S”,这是“Source”的首字母,因此SRPM可以音译为“源代码模式下的RPM包”。 也就是说,SRPM包不再是编译好的二补代码文件,而是源代码文件。 可以理解,SRPM包是软件以源代码形式发布后,直接打包成RPM包的产品。

通过 rpm2cpio 反汇编 kernel-ml-5.15.13-1.el7.elrepo.nosrc.rpm:

$ rpm2cpio kernel-ml-5.15.13-1.el7.elrepo.nosrc.rpm | cpio -idvconfig-5.15.13-x86_64cpupower.configcpupower.servicekernel-ml-5.15.spec744 blocks

可以看到它包含四个文件:

编制计划

1、已经获得了kernel-ml-5.15.13的文件,基于此我们可以制作5.15.126版本所需的内容:

1)将config-5.15.13-x86_64的名称更改为config-5.15.126-x86_64,可以直接使用

2)更改kernel-ml-5.15.spec中LKAver的版本号:

%define LKAver 5.15.13
to
%define LKAver 5.15.126

3)如果已经执行了编译方法1,则需要删除rpmbuild目录,然后执行rpmdev-setuptree命令生成新的rpmbuild目录。

将以下文件复制到 rpmbuild/SOURCES 目录:

config-5.15.126-x86_64cpupower.configcpupower.servicelinux-5.15.126.tar.xz

2.安装依赖项。 ELRepo方式比编译方式需要多安装几个依赖:

$ sudo yum install asciidoc newt-devel xmlto audit-libs-devel binutils-devel elfutils-devel java-1.8.0-openjdk-devel libcap-devel numactl-devel perl python-devel python3 slang-devel xz-devel pciutils-devel perl-ExtUtils-Embed

3.执行编译

执行spec所在目录:

$ rpmbuild -v -bb --clean ./kernel-ml-5.15.spec

执行一次也需要一个小时。 当听到以下内容时,说明制作成功:

Wrote: /home/develop/rpmbuild/RPMS/x86_64/kernel-ml-5.15.126-1.el7.x86_64.rpmWrote: /home/develop/rpmbuild/RPMS/x86_64/kernel-ml-devel-5.15.126-1.el7.x86_64.rpmWrote: /home/develop/rpmbuild/RPMS/x86_64/kernel-ml-headers-5.15.126-1.el7.x86_64.rpmWrote: /home/develop/rpmbuild/RPMS/x86_64/perf-5.15.126-1.el7.x86_64.rpmWrote: /home/develop/rpmbuild/RPMS/x86_64/python-perf-5.15.126-1.el7.x86_64.rpmWrote: /home/develop/rpmbuild/RPMS/x86_64/kernel-ml-tools-5.15.126-1.el7.x86_64.rpmWrote: /home/develop/rpmbuild/RPMS/x86_64/kernel-ml-tools-libs-5.15.126-1.el7.x86_64.rpmWrote: /home/develop/rpmbuild/RPMS/x86_64/kernel-ml-tools-libs-devel-5.15.126-1.el7.x86_64.rpmExecuting(%clean): /bin/sh -e /var/tmp/rpm-tmp.vF4Ure+ umask 022+ cd /home/develop/rpmbuild/BUILD+ cd kernel-ml-5.15.126+ /usr/bin/rm -rf /home/develop/rpmbuild/BUILDROOT/kernel-ml-5.15.126-1.el7.x86_64+ exit 0Executing(--clean): /bin/sh -e /var/tmp/rpm-tmp.7Fu6Tu+ umask 022+ cd /home/develop/rpmbuild/BUILD+ rm -rf kernel-ml-5.15.126+ exit 0

此时源码编译内核,可以在rpmbuild/RPMS/x86_64目录下看到几个编译好的RPM:

total 78164-rw-rw-r-- 1 develop develop 59928964 Aug 12 10:30 kernel-ml-5.15.126-1.el7.x86_64.rpm-rw-rw-r-- 1 develop develop 14431016 Aug 12 10:30 kernel-ml-devel-5.15.126-1.el7.x86_64.rpm-rw-rw-r-- 1 develop develop  1601944 Aug 12 10:30 kernel-ml-headers-5.15.126-1.el7.x86_64.rpm-rw-rw-r-- 1 develop develop  2715444 Aug 12 10:30 perf-5.15.126-1.el7.x86_64.rpm-rw-rw-r-- 1 develop develop   762024 Aug 12 10:30 python-perf-5.15.126-1.el7.x86_64.rpm-rw-rw-r-- 1 develop develop   279844 Aug 12 10:30 kernel-ml-tools-5.15.126-1.el7.x86_64.rpm-rw-rw-r-- 1 develop develop   161168 Aug 12 10:30 kernel-ml-tools-libs-5.15.126-1.el7.x86_64.rpm-rw-rw-r-- 1 develop develop   138332 Aug 12 10:30 kernel-ml-tools-libs-devel-5.15.126-1.el7.x86_64.rpm

可以看到,与第一种形式相比,形成的RPM数量更多,devel-5.15.126的rpm大小也比较小。

实际的devel-5.15.126拆包相比,内眼可见的差异是:

我也找了很久差异的原因源码编译内核,但是没有结果。 如果有大佬知道原因的话,希望能给我一些建议。 先感谢您。

两种形式都可以正常完成内核版本升级,但从占用空间和输出RPM的对比来看,更倾向于使用第二种编译方式,即基于ELRepoProject对SRPM进行修改后编译最新的kernelrpm 。

内核升级

内核升级比较简单,实际升级时只需要这两个RPM文件(针对编译方法2):

kernel-ml-5.15.126-1.el7.x86_64.rpmkernel-ml-devel-5.15.126-1.el7.x86_64.rpm

如果是编译方法一的话就是这两种:

kernel-5.15.126-1.x86_64.rpmkernel-devel-5.15.126-1.x86_64.rpm

其中编译好的kernel-headersrpm在很多文章中都说需要安装,而在我的实际测试中,如果带的话会遇到冲突。 elrepo 官方文档还指出,kernel-headers 不需要升级,只有在重新创建 glibc 和整个操作系统时才需要:

There is no need to install the kernel-ml-headers package. It is only necessary if you intend to rebuild glibc and, thus, the entire operating system. If there is a need to have the kernel headers installed, you should use the current distributed kernel-headers package as that is related to the current version of glibc.

1、安装内核:

yum localinstall kernel-ml-*

2、安装成功后,查看本机存在的内核列表:

awk -F' '$1=="menuentry " {print i++ " : " $2}' /boot/grub2/grub.cfg
0 : CentOS Linux (5.15.126-1.el7.x86_64) 7 (Core)1 : CentOS Linux (3.10.0-862.el7.x86_64) 7 (Core)2 : CentOS Linux (0-rescue-2acea53cb12b4a61b90296add99afcc1) 7 (Core)

3.设置启动最新内核(通常最新安装的内核启动顺序为0)

grub2-set-default 0

4.Reboot重启机器

参考

1.

2.@lists.elrepo.org/msg03172.html

3.

4.

5.

6.

7.%E8%B0%83%E9%A2%91

8.

9.

10.#L1481

11.

12.

13.

Momo ID:苹果尼斯

1、内核编译的基本流程,如有需要,进行修改;;;【根据发布版本生成对应的源码包】;。

步骤是必需的,[ ] 是可选步骤。

如果您不使用发行版的源包管理系统,则无需执行任何步骤

4. 如果要使用源包管理系统进行安装,可以使用每个发行版的源包构建系统。 在这些情况下,步骤 3 和 4 的操作将结合起来。

2. 准备工作 2.1 工具安装源码包名称备注

ncurses-开发

基于控制台(文本界面)设置所需

qt开发

基于窗口(图形界面)设置所需

qt3开发

基于窗口(图形界面)设置所需

gcc-c++

基于窗口(图形界面)设置所需

rpm 构建

生成rpm包需要

源码包名备注

libncurses5-dev

基于控制台(文本界面)设置所需

qt3-开发工具

基于窗口(图形界面)设置所需

克++

基于窗口(图形界面)设置所需

内核包

生成deb包时需要

假根

生成deb包时需要

dpkg-dev

生成deb包时需要

2.2 获取源码

不多说了。参考:一篇文章了解Linux系统内核升级及下载当前内核源码

这里假设源代码(linux2.6)已经下载到当前主目录~/linux-2.6/。

3. 配置

源代码树附带了帮助设置的工具。 这个工具包称为 kconfig。 设置工具有两种类型:基于控制台(文本界面)和基于窗口(图形界面)。 这里主要以控制台工具为例介绍窗口工具。

1、选择目标机的架构,默认配置

在源码树中,为每个架构准备了一个默认的.config文件,位于arch//configs/*_defconfig,执行以下命令:

$ make defconfig

2.根据需要更改内核配置

要启动基于控制台的设置工具,请在源树的根目录下执行以下命令:

$ make menuconfig

[y]键:完成左侧的选择显示。 这意味着该项目已编译并静态添加到内核中。

【m】键,显示完成。 此时,该项目将被编译为模块。 使用此功能时编译内核源码,模块会根据需要动态添加到内核中。

[n]键,将会生成,并且该函数不会被编译。

大致完成你想要的设置后,可以选择菜单顶屏的操作菜单,或者按两次【Esc】键完成设置,在“是否保存新的设置”中选择是按钮。设置?” 出现的对话框,将设置保存到 .config 文件。 至此,内核编译设置完成。

4. 编译 4.1 直线编译

当运行编译内核的目标机是本地时,只需要在源码树的根目录下执行:

$ make

编译时间与机器的性能有很大关系,少则几分钟,多则几个小时。 那么有什么办法可以节省编译时间呢?

在内核的配置中

禁用目标环境中不需要的驱动程序,仅编译必要的功能或模块。关于编译选项

-j选项用于指定make的并发度。 当机器是多处理器时,可以根据处理器的数量来指定该值,这样就可以实现快速编译。在机器性能方面

使用高性能主机进行内核编译。 4.2 交叉编译变量说明

目标机框架

交叉编译

指定交叉编译器的前缀

$ make ARCH=arm CROSS_COMPILE=armv5tel-linux- uImage
$ make ARCH=arm CROSS_COMPILE=armv5tel-linux- modules

$ make ARCH=arm CROSS_COMPILE=armv5tel-linux- INSTALL_MOD_PATH=~/armroot-2.6.38 modules_install

4.3 自定义模块编译

有时,除了嵌入式模块之外,我们还需要编译可加载的模块。 它的源代码和内核源代码树不在同一目录树中,而是单独提供的。 在这些情况下,需要对驱动程序的源代码正确编译Makefile,并按照以下方法编译安装:

$ make –C /lib/modules/$(uname -r)/build M=$PWD
$ make –C /lib/modules/$(uname -r)/build M=$PWD modules_install

-C 选项:到内核源目录的符号链接。

-M 选项:告诉 Linux 内核的构建操作在源代码树之外执行构建操作。

5. 安装 5.1 本地安装

安装分三个阶段进行。

第一阶段是模块的安装,在编译后的源码树根目录下执行

命令:

$ sudo make modules_install

此时,编译好的模块安装在/lib/modules下。

第二阶段是安装内核二进制镜像文件,生成并安装引导初始化文件系统镜像文件。 同样在源码树的根目录下执行以下命令:

$ sudo make install

至此,内核镜像文件就安装在/boot下了。

下表是内核安装生成的文件和目录列表:

文件名或目录名内容

/lib/modules/<内核版本>

模块安装目录

/boot/vmlinuz-<内核版本>

内核映像文件

/boot/initramfs-<内核版本> 或 /boot/initrd.img-<内核版本>

引导初始化文件系统映像

/boot/Systemmap-<内核版本>

地址信息文件

第三阶段更改启动文件。 在某些系统配置下,可能需要自动配置 GRUB 以便能够从当前安装的内核引导。 在这些情况下,请适当编辑 /boot/grub/menu.lst 或执行 update-grub 命令。

此时请重新启动机器,确认新内核是否仍能正常运行。

注意:内核镜像的文件名和模块目录名是根据内核版本命名的。 因此,当重新编​​译和安装已安装版本的内核时,原来安装的内核和模块将被覆盖。 为了避免这些情况,可以在内核配置选项CONFIG_LOCALVERSION中添加字符,该字符将成为内核版本的一部分,因此可以避免被覆盖。

进行对象描述

干净的

将源树恢复到编译前状态。 obj文件被删除,.config或者编译时手动生成的一些文件不会被删除

正确先生

将源码树完全恢复到发布时的状态。发布时源码树中不存在的所有文件都会被删除,包括.config文件

帮助

显示可用的 make 对象

标签

生成标签文件。有了标签文件,就可以使用Emacs等编辑器的标签跳转功能跳转到函数定义,可以高效浏览源代码

范围

生成与 cscope 一起使用的索引文件。 cscope 是一个基于控制台(文本界面)的源浏览器

盟友配置

生成一个 .config 文件,其中启用所有设置项并静态添加到内核

全部无配置

生成.config文件,其中允许范围内的设置项被设置为无效

全部修改配置

生成一个 .config 文件,启用所有可设置为模块的项目并将其设置为模块

/.o

仅执行生成指定目标文件所需的编译。仅指定时,此目录中的所有目标文件均从 .config 文件生成

/.ko

只生成指定的模块

进行选项描述

V=0|1|2

设置编译时控制台显示的详细程度。 默认只显示摘要,设置为0。设置为1时,显示更详细的信息。 设置为2时,除了摘要之外,还会显示编译的原因(原因大多是“由于没有对象”)

奥=

将编译生成的所有文件输出到. 它在严格禁止写入源代码树的情况下非常有用。

5.2 使用包管理工具安装

要将内核镜像纳入包管理范围,需要生成相应的源码包。

$ make rpm-pkg

执行该命令后,将创建一个源码包(SRPM)和一个二进制包(RPM)。 二进制包存放在~/rpmbuild/rpms下编译内核源码,源码包存放在~/rpmbuild/SRPMS下。

如果您有 SRPM 提取的发行版内核的源代码,请使用 rpmbuild 创建源代码包。 如果内核的SRPM解压到~/rpmbuild,则执行以下命令创建源码包:

$ rpmbuild –ba ~/rpmbuild/SPECS/kernel.spec

创建的源码包存放目录与之前相同。 这些源码包与普通源码包相同,可以使用rpm命令进行安装和卸载。

$ make deb-pkg

创建的源码包存放在源码树的根目录下。 生成了几个源码包,其中包含内核镜像和模块的就是linux-image-<内核版本>.deb文件。这些源码包的操作与普通deb源码包文件的操作相同

同样可以使用dpkg来安装。

另外,Ubuntu还在kernel-package包中包含了一个辅助创建内核包的工具——makekpkg命令。 该工具可以通过命令选项来设置创建操作,您也可以根据自己的需要使用该工具。

6. 卸载

注意:卸载内核时请谨慎。 另外,请务必做好修改GRUB设置等工作。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 源码编译 源码编译内核-CentOS7上Linux内核的编译和升级 https://www.wkzy.net/game/125639.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务