内核/升级

From Gentoo Wiki
< Kernel
Jump to:navigation Jump to:search
This page is a translated version of the page Kernel/Upgrade and the translation is 58% complete.
Outdated translations are marked like this.

这篇文章描述了升级到新版本内核的步骤。

从新的源代码制作一个新的内核基本上和安装系统时的制作内核是一样的。唯一的不同之处在于可以将之前保存旧的内核配置文件稍加改变,就可以应用到新内核的构建中,这样就可以避免重新配置一遍所有的内核选项(就好比make menuconfig)。

新内核相较于老内核而言,有一些选项或特性被增加或移除了,因此在新的内核配置文件中有一些旧内核所没有的新条目,并且在旧内核中存在的条目有可能在新内核中没有了。

本文章指导读者将旧内核的配置文件转换为新内核的配置时,如何更改配置文件。

Kernel upgrade in Gentoo involves these steps:

  1. Install the new kernel sources.
  2. Setting the symlink to the (newly installed) kernel sources.
  3. Moving to the new kernel's folder.
  4. Adjusting the .config file for the options introduced to, or removed from, the new kernel's configuration.
  5. Compiling the kernel and the initramfs.
  6. Updating the bootloader.
  7. Removing or keeping the old kernel.
重要
It is wise to make a backup of the kernel configuration so that the previous configurations are not lost. Many users devote considerable time to figure out the best configuration for the system, and losing that information is definitely not wanted. One of the ways introduced in Copy the previous kernel configuration of this article can be used for making a backup of the configuration file.

Emrege 新的内核源码

当安装新的内核源代码后,升级您的内核或许是一个很棒的主意。当您运行以下命令时,新的内核源代码有时会随着系统的更新而安装。

root #emerge --ask --update --deep --with-bdeps=y --newuse @world

当然,也可以使用下面的命令直接安装内核(用任何正在使用的内核版本替换“gentoo-sources”):

root #emerge --ask --update --deep --with-bdeps=y --newuse sys-kernel/gentoo-sources

安装新的内核源代码并不会给使用者提供一个新的内核。从新内核源代码构建和安装一个新的内核,然后重启系统从而真正的运行新的内核是有必要的。

设置一个符号链接到新的内核源代码

The kernel configuration is saved in a file named .config in the directory that holds the kernel sources, a symlink is used to point to that directory.

符号链接 /usr/src/linux 应该始终指向正在运行的内核的源代码的目录。下面三种方法中任意一个可以实现这一点:

  1. 默认:使用eselect设置符号连接
  2. 可选方案1:手动更新符号连接
  3. 可选方案2:使用USE="symlink"安装内核源代码

默认:使用 eselect 设置链接

eselect 设置链接:

user $eselect kernel list
Available kernel symlink targets:
 [1] linux-3.14.14-gentoo *
 [2] linux-3.16.3-gentoo

这将输出可用的内核源代码。星号表示已经选择的来源。

要更改内核源,例如选第二个选项:

root #eselect kernel set 2

备选方案 1:手动更新符号链接

手动设置符号链接:

root #ln -sf /usr/src/linux-3.16.3-gentoo /usr/src/linux
user $ls -l /usr/src/linux
lrwxrwxrwx 1 root root 19 Oct  4 10:21 /usr/src/linux -> linux-3.16.3-gentoo

备选方案 2:安装使用 USE Flag 的内核源代码

这将会让 /usr/src/linux 指向新安装的内核源代码。

如果有必要的话,也可以选择下面两种方法之一来进行稍后修改。

移动到新的内核文件夹

现在已修改符号链接,将工作目录更改为新的内核文件夹。

user $cd /usr/src/linux
附注
即使在修改符号链接时工作目录已经是/usr/src/linux,此命令仍然是必需的。在实际遵循新的符号链接之前,控制台仍将位于内核的目录中。

对新内核调整 .config 文件

复制以前的内核配置文件

旧内核的配置需要被复制到新的内核中。还可以在多个位置找到旧配置:

  • 如果在当前内核中选项Enable access to .config through /proc/config.gz(CONFIG_IKCONFIG_PROC)是激活的,配置文件在procfs 文件系统:
root #zcat /proc/config.gz > /usr/src/linux/.config
root #zcat /proc/config.gz > /usr/src/linux/.config
  • 从老内核中提取。仅当老内核使用CONFIG_IKCONFIG被编译时可用:
root #/usr/src/linux/scripts/extract-ikconfig /path/to/old/kernel >/usr/src/linux/.config
root #/usr/src/linux/scripts/extract-ikconfig /path/to/old/kernel >/usr/src/linux/.config
  • /boot 目录里获取,如果你把配置文件安装到了这里:
root #cp /boot/config-3.14.14-gentoo /usr/src/linux/.config
root #cp /boot/config-3.14.14-gentoo /usr/src/linux/.config
  • 当前运行的内核的源代码目录:
root #cp /usr/src/linux-3.14.14-gentoo/.config /usr/src/linux/
root #cp /usr/src/linux-3.14.14-gentoo/.config /usr/src/linux/
  • In the /etc/kernels/ directory, if SAVE_CONFIG="yes" is set in /etc/genkernel.conf and genkernel was previously used:
root #cp /etc/kernels/kernel-config-x86_64-3.14.14-gentoo /usr/src/linux/.config
root #cp /etc/kernels/kernel-config-x86_64-3.14.14-gentoo /usr/src/linux/.config

更新 .config 文件

附注
Invoking make oldconfig and make menuconfig can be done automatically via genkernel in the build process by enabling the OLDCONFIG and MENUCONFIG parameters in /etc/genkernel.conf. If OLDCONFIG is enabled in genkernel's configuration or if it's going to be enabled by passing --oldconfig option to genkernel command, jump to the build section in this article.

新的内核通常需要新的.config文件去支持新的内核特性。旧内核的.config配置文件可以被转换成新的内核所使用的配置文件,这种转化可以通过make oldconfigmake olddefconfig这两种方式完成

make oldconfig

重要
make syncconfig

有一个内部执行细节:一般会使用make oldconfig完成这个任务,因为make silentoldconfig目标在Linux版本4.19及更高版本中已经被移除了。

下面的配置是基于类似文本的配置 make config 。 对于新的配置,它提供选择。例如:

user $cd /usr/src/linux
root #make oldconfig
Anticipatory I/O scheduler (IOSCHED_AS) [Y/n/m/?] (NEW)

字符串“(NEW)”在该行结束时标记该选项是新的。左边的方括号中的字符串是可能的答案:“Y”是,“N”不是,“m”模块,或者“?”显示帮助。推荐(或者说是默认)答案是大写(“Y”)。帮助说明解释了选项或驱动程序。

可惜 make oldconfig 不会在每一个选项显示太多的信息,例如上下文,因此有时候做出正确的选择比较困难。这种情况下最好的办法就是记住选项的名字,之后通过 配置工具 重新修正。为了跟踪新的选项并且探索这些选项的内容,可以在运行 make oldconfig 后执行 make listnewconfig

制作旧的配置 (make olddefconfig)

运行 make olddefconfig 将会保持所有旧的 .config 选项并且设置新的选项为推荐(或默认)的值

user $cd /usr/src/linux
root #make olddefconfig

make help

使用 make help 查看其他可用的转换方法:

user $make help

观察差异

diff 工具可以用来比较新旧 .config 文件,来查看增加了哪些选项:

user $diff <(sort .config) <(sort .config.old) | awk '/^<.*(=|Linux)/ { $1=""; print }'
CONFIG_64BIT_TIME=y
CONFIG_AMD_NB=y
CONFIG_ARCH_CLOCKSOURCE_INIT=y
CONFIG_ARCH_HAS_GIGANTIC_PAGE=y
CONFIG_ARCH_HAS_PTE_DEVMAP=y
CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
CONFIG_ARCH_STACKWALK=y
CONFIG_ARCH_USE_MEMREMAP_PROT=y
CONFIG_BLK_PM=y
CONFIG_CC_CAN_LINK=y
CONFIG_CC_DISABLE_WARN_MAYBE_UNINITIALIZED=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_KASAN_GENERIC=y
CONFIG_CC_HAS_WARN_MAYBE_UNINITIALIZED=y
CONFIG_CPU_SUP_AMD=y
CONFIG_CPU_SUP_HYGON=y
CONFIG_CPU_SUP_ZHAOXIN=y
CONFIG_CRYPTO_LIB_AES=y
CONFIG_CRYPTO_LIB_ARC4=y
CONFIG_CRYPTO_LIB_DES=y
CONFIG_CRYPTO_LIB_SHA256=y
CONFIG_DEBUG_MISC=y
CONFIG_DRM_I915_FORCE_PROBE=""
CONFIG_DRM_I915_SPIN_REQUEST=5
CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND=250
CONFIG_DYNAMIC_EVENTS=y
CONFIG_EFI_EARLYCON=y
CONFIG_GCC_PLUGINS=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
CONFIG_HAVE_ARCH_STACKLEAK=y
CONFIG_HAVE_ASM_MODVERSIONS=y
CONFIG_HAVE_EISA=y
CONFIG_HAVE_FAST_GUP=y
CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
CONFIG_HAVE_GENERIC_VDSO=y
CONFIG_HAVE_MOVE_PMD=y
CONFIG_HAVE_PCI=y
CONFIG_INIT_STACK_NONE=y
CONFIG_IO_URING=y
CONFIG_KASAN_STACK=1
CONFIG_LEDS_TRIGGER_AUDIO=y
CONFIG_LSM="lockdown,yama,loadpin,safesetid,integrity"
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
CONFIG_NETFILTER_XT_TARGET_MASQUERADE=m
CONFIG_NET_VENDOR_GOOGLE=y
CONFIG_NET_VENDOR_MICROCHIP=y
CONFIG_NET_VENDOR_PENSANDO=y
CONFIG_NET_VENDOR_XILINX=y
CONFIG_NF_NAT=m
CONFIG_NF_NAT_MASQUERADE=y
CONFIG_NVMEM_SYSFS=y
CONFIG_OPTIMIZE_INLINING=y
CONFIG_POWER_SUPPLY_HWMON=y
CONFIG_PROC_PID_ARCH_STATUS=y
CONFIG_SKB_EXTENSIONS=y
CONFIG_SND_INTEL_NHLT=y
CONFIG_UBSAN_ALIGNMENT=y
CONFIG_UNIX_SCM=y
CONFIG_USB_AUTOSUSPEND_DELAY=2
CONFIG_X86_ACPI_CPUFREQ_CPB=y
CONFIG_X86_MCE_AMD=y
# end of Gentoo Linux
# Linux/x86 5.4.0-gentoo Kernel Configuration

以及被移除的选项:

user $diff <(sort .config) <(sort .config.old) | awk '/^>.*(=|Linux)/ { $1=""; print }'
CONFIG_ANON_INODES=y
CONFIG_ARCH_DISCARD_MEMBLOCK=y
CONFIG_ARCH_HAS_SG_CHAIN=y
CONFIG_ARCH_HAS_ZONE_DEVICE=y
CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
CONFIG_ARM_GIC_MAX_NR=1
CONFIG_AUDIT_TREE=y
CONFIG_AUDIT_WATCH=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_DEFAULT_CFQ=y
CONFIG_DEFAULT_IO_DELAY_TYPE=0
CONFIG_DEFAULT_IOSCHED="cfq"
CONFIG_DEFAULT_SECURITY=""
CONFIG_DMA_DIRECT_OPS=y
CONFIG_FB_BACKLIGHT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
CONFIG_HAVE_GENERIC_GUP=y
CONFIG_HAVE_MEMBLOCK=y
CONFIG_IA32_AOUT=y
CONFIG_INET6_XFRM_MODE_BEET=y
CONFIG_INET6_XFRM_MODE_TRANSPORT=y
CONFIG_INET6_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_IO_DELAY_TYPE_0X80=0
CONFIG_IO_DELAY_TYPE_0XED=1
CONFIG_IO_DELAY_TYPE_NONE=3
CONFIG_IO_DELAY_TYPE_UDELAY=2
CONFIG_IOSCHED_CFQ=y
CONFIG_IOSCHED_NOOP=y
CONFIG_MAY_USE_DEVLINK=y
CONFIG_NO_BOOTMEM=y
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_X86_DEV_DMA_OPS=y
# Linux/x86 4.19.86-gentoo Kernel Configuration

另外,内核提供了一个脚本,可以干净地比较两个配置文件,即使已经移动了文件中的选项。

user $/usr/src/linux/scripts/diffconfig .config.old .config

make menuconfig

The options can then be researched and changed if necessary by running:

root #make menuconfig

The menuconfig target is helpful because it safely handles kernel symbol dependency resolution.

编译

重要
当外部内核模块被安装 (如 NVIDIA 或 ZFS),在制作内核前可能需要运行 make modules_prepare ,在这里 有它的描述。在构建上述额外的模块之前,一些模块在内核构建之前不能被安装或准备好。

Having configured the new kernel as described in the previous sections, if external kernel modules are installed (like nvidia or zfs), it may be necessary to prepare them before building the new kernel, and then to rebuild the modules with the newly built kernel:

root #make modules_prepare
附注
Using the -jN option with make (where N is the number of parallel jobs) can speed up the compilation process on multi-threaded systems. For example, make -j5 on a system with four logical cores.

Having built both the kernel and the modules, both should be installed:

root #make modules_install
root #make install

Finally, the bootloader must be reconfigured to account for the new kernel filenames, as described below. initramfs must be rebuilt if one is used as well.

自动构建和安装

可以使用Portage钩子自动构建和安装新出现的内核。虽然其他方法也是可行的,但以下内容基于genkernel和gentoo-sources包。它需要以下先决条件:

  1. genkernel all能够构建和安装内核到/usr/src/linux符号链接指向的$BOOTDIR和引导程序。
  2. 为内核ebuild设置了symlink use标志。

如果满足这些要求,只需安装post_pkg_postinst Portage钩子,如下所示。

文件 /etc/portage/env/sys-kernel/gentoo-sources自动构建和安装内核的 portage hook
post_pkg_postinst() {
# Eselect the new kernel or genkernel will build the current one
	eselect kernel set linux-"${PV}"-gentoo
	CURRENT_KV=$(uname -r)
# Check if genkernel has been run previously for the running kernel and use that config
	if [[ -f "${EROOT}/etc/kernels/kernel-config-${CURRENT_KV}" ]] ; then
		genkernel --kernel-config="${EROOT}/etc/kernels/kernel-config-${CURRENT_KV}" all
# Use latest kernel config from current kernel
	elif [[ -f "${EROOT}/usr/src/linux-${CURRENT_KV}/.config" ]] ; then
		genkernel --kernel-config="${EROOT}/usr/src/linux-${CURRENT_KV}/.config" all
# Use known running good kernel
	elif [[ -f /proc/config.gz ]] ; then
		zcat /proc/config.gz >> "${EROOT}/tmp/genkernel.config"
		genkernel --kernel-config="${EROOT}/tmp/genkernel.config" all
		rm "${EROOT}/tmp/genkernel.config"
# No valid configs known, compile a clean one
	else
		genkernel all
	fi
}

解决编译的问题

当重新编译当前内核的时候遇到问题,这也许有助于净化内核源代码。确保首先备份了.config文件,因为操作过程会删除它。确保备份文件不要以 .bak 或者 ~ 为后缀,因为 make distclean 同样会删除这些文件。

root #cp .config /usr/src/kernel_config_bk
root #make distclean
root #mv /usr/src/kernel_config_bk .config

升级启动引导

The upgraded and installed kernel must be registered with the bootloader or directly with the UEFI firmware, see Kernel/Configuration. Users of GRUB can use the method below, users of other bootloaders must consult the Handbook.

之后,确保挂载了 /boot 分区,

使用 grub-mkconfig

The following command can be executed for updating GRUB's configuration file:

root #grub-mkconfig -o /boot/grub/grub.cfg
警告
If GRUB itself was upgraded (besides the kernel), for instance as part of a world set upgrade, it is necessary to also re-install GRUB, otherwise it may not boot. See GRUB#GRUB Bootloader Installation for details.
提示
By enabling the grub USE flag on sys-kernel/installkernel grub-mkconfig will be regenerated automatically every time a new kernel is installed.

使用 systemd-boot-gen 升级 systemd-boot UEFI 配置文件

A systemd-boot configuration file for the new kernel is generated automatically when the kernel is installed. No manual action is required.

移除旧的内核

参考 移除旧的内核

另请参阅

外部资源