目录

一、获取内核源码

二、安装编译内核依赖的工具

三、配置内核相关参数项

四、编译内核源码

五、安装新内核及其内核模块

六、生成initramfs文件系统

七、更新grub配置

八、重启系统生效


本文介绍如何编译linux源码,然后以编译后的新内核启动linux系统,可能在比较老的系统版本上编译会有问题。

一、获取内核源码

官网拉取所要编译的指定版本linux代码

官网:The Linux Kernel Archives

 或者从git上git clone源码:

# git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

国内git clone会比较慢,可以自行加梯子或者gitee上下载,下载到源码后,解压待使用。

tar.xz格式的使用unxz或者xz -d或者tar -zxf来解压;

zip包用unzip解压;

tar tar.gz用tar xf解压。

二、安装编译内核依赖的工具

主要是开发套件相关工具及组件,比如gcc或者clang及相关软件包。

1、Debian/Ubuntu

# apt-get install build-essential libncurses-dev bison flex libssl-dev libelf-dev

2、Fedora/RHEL/CentOS/Oracle Linux

# yum group install "Development Tools"
# yum install ncurses-devel bison flex elfutils-libelf-devel openssl-devel

3、Fedora

# dnf group install "Development Tools"
# dnf install ncurses-devel bison flex elfutils-libelf-devel openssl-devel

4、Arch linux/Manjaro

 安装完系统要再次更新下:

# pacman -Syyu
# pacman -S gcc bc libelf flex bison make cmake

或者LLVM/clang工具链安装:

# pacman -S clang llvm lld bc flex bison make cmake unzip

注:下面执行命令都要在要编译的内核源码根目录下进行

三、配置内核相关参数项

1、首先,可以复用本机的config文件

# cp -v /boot/config-$(uname -r) /new_kernel_src_path/.config

或者

# zcat /proc/config.gz > /new_kernel_src_path/.config

注意:这里是把本机config配置拷贝到我们前面解压出来的内核源码根目录下。

2、配置内核参数

基于文本的菜单配置,适用性强,也可用于远程编译内核

# make menuconfig

当然如果系统带有桌面,可以选择如下的图形界面菜单配置内核:

①如果系统是基于KDE桌面或者最新的QT库,可以使用:

# make xconfig

②如果系统基于gtk的库,如Gnome或者xfce桌面,可以使用:

# make gconfig

当然,你可以执行make allyesconfig或者make allnoconfig简单的将内核所有可配置的配置都启用或者禁用。

3、如果之前编译过内核源码,由于出错或者其它原因想重新编译,则需要先清理下之前的编译结果,执行:

# make mrproper

注:如果下面使用LLVM/clang工具构建内核的话,会报错如下:

   BTF: .tmp_vmlinux.btf: pahole (pahole) is not available
    Failed to generate BTF for vmlinux
    Try to disable CONFIG_DEBUG_INFO_BTF
    make: *** [Makefile:1170: vmlinux] Error 1

解决方案:

①、安装包含pahole的软件包

②、禁用掉CONFIG_DEBUG_INFO_BTF功能,可以在make menuconfig菜单中找到,,然后按空格键取消掉:

Main menu

        -> Kernel hacking

                ->Compile-time checks and compiler options

                        -> Compile the kernel with debug info(DEBUG_INFO [=y])

四、编译内核源码

执行make命令即可,但是内核源码庞大,编译下来很费时间(跟机器性能有关,一般需要数十分钟到几个小时),可以make加上-jn选项多线程编译内核来加速内核编译,如:

# j后面数字,可以设置成cpu个数
# make -j4

如果使用LLVM/clang工具链编译,则可以:

# make LLVM=1 -j4
或者
# make CC=clang LD=ld.bfd -j4

注:此时可以干的别的,这个过程比较慢,普通机器一般会在小时级别。

五、安装新内核及其内核模块

1、通常情况下,编译没报错的话,此时可以安装新内核了,但是我们还是检查下arch/x86/boot/bzImage文件是否已经生成:

# ls arch/x86/boot/bzImage -lh

如果没生成,此时还需要执行:

# make bzImage

生成内核压缩镜像文件,此文件不生成的话,在后面make install的时候会报错:

[root@fedora linux-rust]# make install
sh ./arch/x86/boot/install.sh 5.16.0-rc3 \
        arch/x86/boot/bzImage System.map "/boot"

 *** Missing file: arch/x86/boot/bzImage
 *** You need to run "make" before "make install".

make: *** [arch/x86/Makefile:262:install] 错误 1
[root@fedora linux-rust]# 

2、安装内核新生成的内核模块(驱动)

# make modules_install

3、安装生成新内核,这里可以有多种方法

 ①、执行make install命令,安装内核及其内核模块,这个命令会帮我们把新生成的内核相关文件拷贝到/boot下:

# make install

②、手动复制内核相关文件到/boot/目录下,主要是bzImage文件、system map文件

# cp arch/x86/boot/bzImage  /boot/new_bzImage_name
# cp System.map /boot/new_system_map_name

执行没报错的话,会在/boot/下生成新内核镜像vmlinuz、initramfs及systemmap文件:

注:此阶段可能出现的报错问题:

①、如下报错:

  AS      arch/x86/boot/compressed/efi_thunk_64.o
  OBJCOPY arch/x86/boot/compressed/vmlinux.bin
  RELOCS  arch/x86/boot/compressed/vmlinux.relocs
  ZSTD22  arch/x86/boot/compressed/vmlinux.bin.zst
/bin/sh:行1: zstd:未找到命令
make[2]: *** [arch/x86/boot/compressed/Makefile:136:arch/x86/boot/compressed/vmlinux.bin.zst] 错误 127
make[2]: *** 正在删除文件“arch/x86/boot/compressed/vmlinux.bin.zst”
make[1]: *** [arch/x86/boot/Makefile:115:arch/x86/boot/compressed/vmlinux] 错误 2
make: *** [arch/x86/Makefile:252:bzImage] 错误 2

此时,只需安装zstd,然后重新执行make install即可:

[root@fedora linux-rust]# dnf install zstd
上次元数据过期检查:1:57:52 前,执行于 2021年12月07日 星期二 08时44分53秒。
依赖关系解决。
======================================================================================================================================================
 软件包                          架构                              版本                                       仓库                               大小
======================================================================================================================================================
安装:
 zstd                            x86_64                            1.5.0-2.fc35                               fedora                            639 k

事务概要
======================================================================================================================================================
安装  1 软件包

总下载:639 k
安装大小:1.9 M
确定吗?[y/N]: y
下载软件包:
zstd-1.5.0-2.fc35.x86_64.rpm                                                                                          1.0 MB/s | 639 kB     00:00    
------------------------------------------------------------------------------------------------------------------------------------------------------
总计                                                                                                                  409 kB/s | 639 kB     00:01     
运行事务检查
事务检查成功。
运行事务测试
事务测试成功。
运行事务
  准备中  :                                                                                                                                       1/1 
  安装    : zstd-1.5.0-2.fc35.x86_64                                                                                                              1/1 
  运行脚本: zstd-1.5.0-2.fc35.x86_64                                                                                                              1/1 
  验证    : zstd-1.5.0-2.fc35.x86_64                                                                                                              1/1 

已安装:
  zstd-1.5.0-2.fc35.x86_64                                                                                                                            

完毕!
[root@fedora linux-rust]# 
[root@fedora linux-rust]# make install
sh ./arch/x86/boot/install.sh 5.16.0-rc3 \
        arch/x86/boot/bzImage System.map "/boot"
[root@fedora linux-rust]# 

②、如下报错:

  CALL    scripts/atomic/check-atomics.sh
  RUSTC L rust/core.o
make[1]: *** [rust/Makefile:349:rust/core.o] 错误 137
make: *** [Makefile:1267:prepare0] 错误 2

make[1]: *** [rust/Makefile:349:rust/core.o] 错误 137,这个错误一般是没有交换区导致的编译失败,可以手动添加交换区:

[yg-vm ~]# free -h
               total        used        free      shared  buff/cache   available
内存:      1.9Gi       1.1Gi       529Mi       153Mi       301Mi       529Mi
交换:         0B          0B          0B
[yg-vm ~]# 
[yg-vm ~]# dd if=/dev/zero of=/swapfile bs=1k count=2048000
记录了2048000+0 的读入
记录了2048000+0 的写出
2097152000字节(2.1 GB,2.0 GiB)已复制,7.39818 s,283 MB/s
[yg-vm ~]# 
[yg-vm ~]# mkswap /swapfile 
mkswap: /swapfile: insecure permissions 0644, fix with: chmod 0600 /swapfile
正在设置交换空间版本 1,大小 = 2 GiB (2097147904  个字节)
无标签,UUID=e9f4e3a3-4d8d-49af-9307-8f880b6d4d20
[yg-vm ~]# 
[yg-vm ~]# 
[yg-vm ~]# 
[yg-vm ~]# swapon /swapfile 
swapon: /swapfile:不安全的权限 0644,建议使用 0600。
[yg-vm ~]# free -h
               total        used        free      shared  buff/cache   available
内存:      1.9Gi       1.1Gi        65Mi       153Mi       763Mi       520Mi
交换:      2.0Gi          0B       2.0Gi
[yg-vm ~]# 

然后再执行make install即可。

③、我在manjaro linux上编译内核时,出现下面报错:

[yg-vm linux-rust]# make install
sh ./arch/x86/boot/install.sh 5.16.0-rc3-MANJARO \
        arch/x86/boot/bzImage System.map "/boot"
Cannot find LILO.
[yg-vm linux-rust]# 

Cannot find LILO.于是我打开vim ./arch/x86/boot/install.sh脚本,看到这个报错是在脚本的最后出现,其实此时内核已经编译安装完成了,可以看下/boot下已经生成了新内核相关文件,所以此报错可以忽略

六、生成initramfs文件系统

对于Fedora及其衍生系统RHEL/CentOS/Oracle Linux、Debian/Ubuntu,在上面make阶段,initramfs都会自动生成。

针对Manjaro/Arch linux系统,编译安装完内核后,还需要手动生成initramfs文件系统

可以使用mkinitcpio工具来生成:

①、将前面编译安装新生成vmlinuz重命名为带版本号的容易标识的名称

[yg-vm linux-rust]# ls -tlh /boot/
总用量 124M
-rw-r--r-- 1 root root 5.7M 12月  4 18:16 System.map
-rw-r--r-- 1 root root 8.6M 12月  4 18:16 vmlinuz
-rw-r--r-- 1 root root 5.7M 12月  4 14:40 System.old
-rw-r--r-- 1 root root 8.6M 12月  4 14:40 vmlinuz.old
drwxr-xr-x 6 root root 4.0K 12月  4 02:00 grub
-rw-r--r-- 1 root root  29M 12月  4 02:00 initramfs-5.10-x86_64-fallback.img
-rw-r--r-- 1 root root 7.9M 12月  4 02:00 initramfs-5.10-x86_64.img
-rw-r--r-- 1 root root 9.1M 12月  4 02:00 vmlinuz-5.10-x86_64
-rw-r--r-- 1 root root  30M 12月  4 01:22 initramfs-5.4-x86_64-fallback.img
-rw-r--r-- 1 root root 8.4M 12月  4 01:22 initramfs-5.4-x86_64.img
-rw-r--r-- 1 root root 7.1M 12月  4 01:22 vmlinuz-5.4-x86_64
-rw-r--r-- 1 root root   22 11月 13 04:24 linux510-x86_64.kver
-rw-r--r-- 1 root root   22 11月 13 04:24 linux54-x86_64.kver
drwxr-xr-x 2 root root 4.0K 10月 18 01:01 memtest86+
-rw-r--r-- 1 root root 4.6M  6月  9 02:31 intel-ucode.img
[yg-vm linux-rust]# mv /boot/vmlinuz /boot/vmlinuz-5.16.0-rc3-x86_64
[yg-vm linux-rust]# 

②、参考本机的preset文件,创建一个新内核的preset文件。

[yg-vm linux-rust]# cd /etc/mkinitcpio.d/
[yg-vm mkinitcpio.d]# ls
linux510.preset  linux54.preset
[yg-vm mkinitcpio.d]# cat linux510.preset 
# mkinitcpio preset file for the 'linux510' package

ALL_config="/etc/mkinitcpio.conf"
ALL_kver="/boot/vmlinuz-5.10-x86_64"

PRESETS=('default' 'fallback')

#default_config="/etc/mkinitcpio.conf"
default_image="/boot/initramfs-5.10-x86_64.img"
#default_options=""

#fallback_config="/etc/mkinitcpio.conf"
fallback_image="/boot/initramfs-5.10-x86_64-fallback.img"
fallback_options="-S autodetect"
[yg-vm mkinitcpio.d]# 
[yg-vm mkinitcpio.d]# 
[yg-vm mkinitcpio.d]# cp linux510.preset linux516.preset

然后将新拷贝的linux516.preset文件里,vmlinuz-5.10-x86_64、initramfs-5.10-x86_64.img、initramfs-5.10-x86_64-fallback.img改为新版本内核的相关文件名,我这里是把5.10-x86_64都改成5.16.0-rc3-x86_64即可,之后执行:

[yg-vm mkinitcpio.d]# mkinitcpio -p linux516.preset 
/usr/bin/mkinitcpio:行268: /etc/mkinitcpio.d/linux516.preset.preset: 没有那个文件或目录
==> ERROR: Failed to load preset: `/etc/mkinitcpio.d/linux516.preset.preset'
[yg-vm mkinitcpio.d]#

此时报错说找不到linux516.preset.preset,可见mkinitcpio命令,自动将-p后的文件加了preset后缀了,此时只需把linux516.preset的后缀去掉即可:

[yg-vm mkinitcpio.d]# cp linux516.preset linux516

然后重新mkinitcpio即可:

[yg-vm mkinitcpio.d]# mkinitcpio -p linux516
==> Building image from preset: /etc/mkinitcpio.d/linux516.preset: 'default'
  -> -k /boot/vmlinuz-5.16.0-rc3-x86_64 -c /etc/mkinitcpio.conf -g /boot/initramfs-5.16.0-rc3-x86_64.img
==> Starting build: 5.16.0-rc3-MANJARO
  -> Running build hook: [base]
  -> Running build hook: [udev]
  -> Running build hook: [autodetect]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
  -> Running build hook: [keyboard]
  -> Running build hook: [keymap]
loadkeys: Unable to open file: cn: No such file or directory
  -> Running build hook: [consolefont]
==> WARNING: consolefont: no font found in configuration
  -> Running build hook: [filesystems]
  -> Running build hook: [fsck]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-5.16.0-rc3-x86_64.img
==> Image generation successful
==> Building image from preset: /etc/mkinitcpio.d/linux516.preset: 'fallback'
  -> -k /boot/vmlinuz-5.16.0-rc3-x86_64 -c /etc/mkinitcpio.conf -g /boot/initramfs-5.16.0-rc3-x86_64-fallback.img -S autodetect
==> Starting build: 5.16.0-rc3-MANJARO
  -> Running build hook: [base]
  -> Running build hook: [udev]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
==> WARNING: Possibly missing firmware for module: xhci_pci
  -> Running build hook: [keyboard]
  -> Running build hook: [keymap]
loadkeys: Unable to open file: cn: No such file or directory
  -> Running build hook: [consolefont]
==> WARNING: consolefont: no font found in configuration
  -> Running build hook: [filesystems]
  -> Running build hook: [fsck]
==> Generating module dependencies
==> Creating gzip-compressed initcpio image: /boot/initramfs-5.16.0-rc3-x86_64-fallback.img
==> Image generation successful
[yg-vm mkinitcpio.d]# 

此时大功告成。

七、更新grub配置

一般上面编译完成后,在新版本的linux发行版中,都会自动将最新编译的高版本内核加入到启动项里的,不放心的话,还是手动修改下grub2 boot loader启动配置:

1、Fedora/RHEL/CentOS/Oracle Linux

# grub2-mkconfig -o /boot/grub2/grub.cfg
# grubby --set-default /boot/vmlinuz-5.6.9

修改后可以查看下是否修改成功:

# grubby --default-kernel
# grubby --default-index
# grubby --info=ALL

2、Debian/Ubuntu linux

# update-initramfs -c -k new_kernel
# update-grub

3、Arch Linux/Manjaro

[yg-vm mkinitcpio.d]# update-grub 
正在生成 grub 配置文件 ...
找到主题:/usr/share/grub/themes/manjaro/theme.txt
找到 Linux 镜像:/boot/vmlinuz-5.16.0-rc3-x86_64
找到 initrd 镜像:/boot/intel-ucode.img /boot/initramfs-5.16.0-rc3-x86_64.img
Found initrd fallback image: /boot/initramfs-5.16.0-rc3-x86_64-fallback.img
找到 Linux 镜像:/boot/vmlinuz-5.10-x86_64
找到 initrd 镜像:/boot/intel-ucode.img /boot/initramfs-5.10-x86_64.img
Found initrd fallback image: /boot/initramfs-5.10-x86_64-fallback.img
找到 Linux 镜像:/boot/vmlinuz-5.4-x86_64
找到 initrd 镜像:/boot/intel-ucode.img /boot/initramfs-5.4-x86_64.img
Found initrd fallback image: /boot/initramfs-5.4-x86_64-fallback.img
警告: os-prober will be executed to detect other bootable partitions.
Its output will be used to detect bootable binaries on them and create new boot entries.
Found memtest86+ image: /boot/memtest86+/memtest.bin
完成
[yg-vm mkinitcpio.d]# 

八、重启系统生效

执行如下命令,重启系统:

# reboot
或者
# init 6

重启系统时,如果能看到开机界面,此时在内核启动项那里已经可以看到新编译的内核了。

启动后,使用命令查看当前内核版本:

# uname -a

参考链接:How to build and install your own Linux kernel - LQWiki

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐