CentOS 7 上编译安装Linux内核
前段时间碰到一些内核bug,需要回合到目前版本,因此稍微研究下内核编译,都是些基本的操作,供后续自己参考。编译分为两种方式,一种是官网src.rpm编译,另外一种用源代码编译。
centos版本:CentOS Linux release 7.4.1708 (Core)
当前系统内核版本:3.10.0-693.5.2.el7.x86_64
待编译的内核版本:3.10.0-693.21.1.el7.x86_64
编译内核需要配置config文件,最好取相同版本的.config文件做修改(/boot/config-*),以匹配当前的内核编译,避免不必要的错误,例如多余的参数或者少参数。
1.官网src.rpm编译
rpm包的编译和其他的rpm编译类似,基本没有区别。
-
rpm包编译
下载: wget http://vault.centos.org/7.4.1708/updates/Source/SPackages/kernel-3.10.0-693.21.1.el7.src.rpm 安装源码包: rpm -ivh kernel-3.10.0-693.21.1.el7.src.rpm 编译准备: rpmbuild -bp /root/rpmbuild/SPECS/kernel.spec 编译内核(时间比较长,生产与内核相关的rpm包,如果生成src包,则执行-ba): rpmbuild -bb /root/rpmbuild/SPECS/kernel.spec
-
注意点
-
编译准备时,需要相应的软件包,例如:
rpmbuild -bp /root/rpmbuild/SPECS/kernel.spec error: Failed build dependencies: bc is needed by kernel-3.10.0-693.21.1.el7.x86_64 xmlto is needed by kernel-3.10.0-693.21.1.el7.x86_64 asciidoc is needed by kernel-3.10.0-693.21.1.el7.x86_64 hmaccalc is needed by kernel-3.10.0-693.21.1.el7.x86_64 newt-devel is needed by kernel-3.10.0-693.21.1.el7.x86_64 perl(ExtUtils::Embed) is needed by kernel-3.10.0-693.21.1.el7.x86_64 pesign >= 0.109-4 is needed by kernel-3.10.0-693.21.1.el7.x86_64 elfutils-devel is needed by kernel-3.10.0-693.21.1.el7.x86_64 binutils-devel is needed by kernel-3.10.0-693.21.1.el7.x86_64 bison is needed by kernel-3.10.0-693.21.1.el7.x86_64 java-devel is needed by kernel-3.10.0-693.21.1.el7.x86_64
安装相应的包即可,其中perl(ExtUtils::Embed)此依赖安装perl-ExtUtils-Embed即可。
yum install perl-ExtUtils-Embed
-
执行bp后,在~/rpmbuild/SOURCES中可以看到相关的默认配置文件
-rw-rw-r--. 1 root root 123782 Mar 6 2018 kernel-3.10.0-ppc64.config -rw-rw-r--. 1 root root 124062 Mar 6 2018 kernel-3.10.0-ppc64-debug.config -rw-rw-r--. 1 root root 123388 Mar 6 2018 kernel-3.10.0-ppc64le.config -rw-rw-r--. 1 root root 123679 Mar 6 2018 kernel-3.10.0-ppc64le-debug.config -rw-rw-r--. 1 root root 59564 Mar 6 2018 kernel-3.10.0-s390x.config -rw-rw-r--. 1 root root 59170 Mar 6 2018 kernel-3.10.0-s390x-debug.config -rw-rw-r--. 1 root root 31654 Mar 6 2018 kernel-3.10.0-s390x-kdump.config -rw-rw-r--. 1 root root 140960 Mar 6 2018 kernel-3.10.0-x86_64.config -rw-rw-r--. 1 root root 141164 Mar 6 2018 kernel-3.10.0-x86_64-debug.config
内核编译所需.config文件的修改不需要通过生成patch来进行修改,上述配置文件用于生成编译内核所需要的配置文件即:
~/rpmbuild/BUILD/kernel-3.10.0-693.21.1.el7/linux-3.10.0-693.21.1.el7.x86_64/.config
编译时根据不同的平台会选择相应的配置。本文属于x86_64,因此在执行bp或者bb后会根据以下两种文件生成配置,修改内核参数修改以下两个文件即可。
-rw-rw-r--. 1 root root 140960 Mar 6 2018 kernel-3.10.0-x86_64.config -rw-rw-r--. 1 root root 141164 Mar 6 2018 kernel-3.10.0-x86_64-debug.config
-
config文件的配置项是有依赖关系的,在执行build生成config时会做检测。
例如:CONFIG_STRICT_DEVMEM参数是控制使用mmap映射/dev/mem文件功能的选项,依赖于CONFIG_X86_PAT,如果不取消CONFIG_X86_PAT,调用mmap()的时候会出现Invalid Parameter错误。但是CONFIG_X86_PAT又依赖于CONFIG_EXPERT,开启CONFIG_EXPERT需要更改一系列的参数,因此
在修改config文件时需要注意下依赖关系,这也是推荐使用make menuconfig图形化修改参数的原因,图形化页面会处理依赖。
-
patch制作后,修改spec文件:
# empty final patch to facilitate testing of kernel patches Patch999999: linux-kernel-test.patch Patch1000: debrand-single-cpu.patch Patch1001: debrand-rh_taint.patch Patch1002: debrand-rh-i686-cpu.patch Patch1003: xxx.patch ... ApplyOptionalPatch linux-kernel-test.patch ApplyOptionalPatch debrand-single-cpu.patch ApplyOptionalPatch debrand-rh_taint.patch ApplyOptionalPatch debrand-rh-i686-cpu.patch ApplyOptionalPatch xxx.patch
-
编译报错compile不支持
make -s ARCH=x86_64 V=1 -j4 KCFLAGS= 'WITH_GCOV= 0' bzImage arch/x86/Makefile:166: *** CONFIG_RETPOLINE=y, but not supported by the compiler. Toolchain update recommended.. Stop. error: Bad exit status from /var/tmp/rpm-tmp.vbZbJO (%build)
错误是因为gcc的版本太低,不支持CONFIG_RETPOLINE=y选项,升级gcc即可。
-
CONFIG_STRICT_DEVMEM的解决方式
由于配置项的依赖关系,暂时不做修改CONFIG_EXPERT以及CONFIG_X86_PAT,仅仅修改
# CONFIG_STRICT_DEVMEM is not set
在编译完内核后,在新内核的启动项中关闭CONFIG_X86_PAT,即在/boot/grub2/grub.cfg中内核启动选项中添加 nopat选项即可。
linux16 /vmlinuz-3.10.0-693.21.1.el7.x86_64 root=/dev/mapper/centos-root ro crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb nopat quiet LANG=en_US.UTF-8 initrd16 /initramfs-3.10.0-693.21.1.el7.x86_64.img
-
编译后的内核支持启动参数的方式更改默认行为,与编译时更改配置效果一致,支持的功能参数可以参见参考文档,内核启动参数修改后,重启生效。
-
2.源代码编译
从内核官网下载内核的源代码,切换到相应的分支或者tag:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
或者从src.rpm安装包,执行
rpmbuild -bp /root/rpmbuild/SPECS/kernel.spec
进入目录
~/rpmbuild/BUILD/kernel-3.10.0-693.21.1.el7/linux-3.10.0-693.21.1.el7.x86_64
-
准备.config文件
编译内核需要配置config文件,最好取相同版本的.config文件做修改(/boot/config-*),以匹配当前的内核编译,避免不必要的错误,例如多余的参数或者少参数。.config中的参数含义:
=y:打到核心里,以后放在vmlinux中 =m:模块方式,以后就表现为 ko文件 not set:该功能不启用
-
配置内核选项,执行
make menuconfig
如果缺少包,安装即可。图形化的config配置并不是显示config中的配置项,而是以更有好的文字说明配置功能,可以按”/”快捷键来搜索config中的配置项,然后输入搜索到的配置项前面的数字即可。例如搜索配置项CONFIG_ASYNC_RAID6_TEST,显示
Symbol: BUILD_DOCSRC [=y] x Type : boolean x Prompt: Build targets in Documentation/ tree x Location: x (1) -> Kernel hacking x Defined at lib/Kconfig.debug:1438 x Depends on: HEADERS_CHECK [=y]
输入1即可调转到相应的配置。
General setup —>的子菜单 Local version - append to kernel release 进入这一项可以写自己编译安装后的内核版本名,为了后面编译出来的包不与当前内核包冲突。
-
编译
make -j 16
j参数后面跟的是cpu核数,用几个cpu来编译,编译时间稍微长些,初次编译缺少包,安装即可。
-
安装module
make modules_install
默认会安装到/usr/lib/modules目录,当然也可以指定相应的安装目录
make modules_install INSTALL_MOD_PATH=/home/test/build/
-
安装内核
make install
安装后到/boot目录下查看相应的内核文件
-
验证新内核
重启主机在菜单页面选择新安装的内核进入即可。
-
生成rpm安装包
在源代码包中直接执行下面命令也可以生成相应的rpm包,用于安装到其他主机。这个时间比较长,因为会成成与内核相关的所有包。
make rpm
但是从centos下载的3.10.0-693.21.1.el7.x86_64源代码 中执行报错,估计是版本的缺陷。
参考文档: