Linux内核开发——编译Ubuntu 20.04内核代码

本文档详细介绍了Linux内核的编译过程,包括查看内核版本、下载源码、解压、配置环境、安装依赖、编译、安装、异常处理等步骤。此外,还讲解了如何配置ccache加速编译,并阐述了如何编译指定模块、制作deb安装文件。整个流程覆盖了从源码获取到内核模块的单独编译和加载,以及制作安装包的方法。
摘要由CSDN通过智能技术生成

1. 完整编译

1.1. 查看内核版本

可以使用下列

uname -r
5.13.0

1.2. 下载内核代码

可以直接下载一个比当前内核版本新的代码,也可以去https://mirrors.edge.kernel.org/pub/linux/kernel下载自己内核使用的版本。此文下载的是更新的版本 5.17.15,去官网https://www.kernel.org/,下载linux-5.17.12.tar.xz。

1.3. 解压

tar -xavf linux-5.17.12.tar.xz

1.4. 配置环境

1.4.1. 更换源

不同版本的Ubuntu,需要对应不同版本的源。可以通过。https://mirror.tuna.tsinghua.edu.cn/help/ubuntu/上可以选择不同版本的Ubuntu对应的源。

# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-security main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-security main restricted universe multiverse

# 预发布软件源,不建议启用
# deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse
# deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse

将上述内核拷贝进下面打开的文件。

sudo gedit /etc/apt/sources.list

拷贝完了之后,更新源

sudo apt-get update

1.4.2. 安装依赖

sudo apt-get install gcc g++
sudo apt-get install libncurses5-dev 
sudo apt-get install build-essential
sudo apt-get install kernel-package 
sudo apt-get install libssl-dev
sudo apt-get install libc6-dev 
sudo apt-get install bin86
sudo apt-get install flex 
sudo apt-get install bison  
sudo apt-get install qttools5-dev  
sudo apt-get install libelf-dev

1.5. 编译

1.5.1. 清理

首次编译可以不用清理,编译之后如果想完整重新编译,可以使用清理命令。

# make mrproper会删除配置的.config以及其他备份
sudo make mrproper 
# make clean会删除编译过程中生成的中间文件和内核镜像文件
sudo make clean

1.5.2. 配置内核

内核的编译配置放在.config文件中,内核arch目录中有提供不同架构的推荐.config供参考。也可以从当前内核的源usr/src/xxx目录中拷贝.config文件到当前目录。如果使用内核自带的参考.config。
可以使用命令:

make xconfig

会启动一个Qt的配置窗口,默认保存即可。

1.5.3. 编译

  1. 全部编译
    # 编译内核镜像及其他所有模块,-j6指定6个线程进行编程,提升编译效果
    sudo make -j6
    
  2. 单独编译
    # 编译内核镜像
    sudo make bzImage -j6
    # 编译其他所有模块
    sudo make modules -j6
    

1.5.4. 安装

安装其实就是将生成的ko库文件拷贝到指定目录lib\modules。

sudo make modules_install -j6  

1.5.5. 安装启动文件

分别生成initrd文件,将镜像文件和map文件拷贝到boot目录。

sudo mkinitramfs /lib/modules/5.17.12 -o /boot/initrd.img-5.17.12
sudo cp arch/x86/boot/bzImage /boot/vmlinuz-5.17.12
sudo cp System.map /boot/System.map-5.17.12

1.5.6. 更新grub

更新grub文件,命令会自动检测boot目录中的initrd文件,将最新的initrd文件设置为默认启动版本。

sudo update-grub

1.6. 重启验证

重启电脑,在终端查看版本号

uname -r 
5.17.12

1.7. 异常处理

  1. 提示相关库缺失,自行安装相关库依赖。
  2. 提示“make[1]: *** No rule to make target ‘debian/certs/benh@debian.org.cert.pem’, needed by ”,将下面的内存修改为空
    CONFIG_SYSTEM_TRUSTED_KEYS=“debian/canonical-certs.pem”
    CONFIG_SYSTEM_REVOCATION_KEYS=“debian/canonical-revoked-certs.pem”
    新值
    CONFIG_SYSTEM_TRUSTED_KEYS=“”
    CONFIG_SYSTEM_REVOCATION_KEYS=“”
  3. 提示“BTF: .tmp_vmlinux.btf: pahole (pahole) is not available”时,修改
    CONFIG_DEBUG_INFO_BTF=y

    CONFIG_DEBUG_INFO_BTF=n

1.8. 配置ccache

为了加速gcc编译内核,编译过的文件可以缓存起来,再次编译时就不用编译了。

1.8.1. 安装

sudo apt install ccache

1.8.2. 配置

sudo gedit ~/.bashrc 
#在末尾回车,添加如下语句,注意ubuntu要改成你的用户名。
export CCACHE_DIR="/home/ubuntu/.ccache"  
export CC="ccache gcc" export CXX="ccache g++" 
export PATH="$PATH:/usr/lib/ccache" 
#Ctrl+S或点击“保存”按钮保存,然后使其生效。
source ~/.bashrc     
#20G是cache大小,可以自行指定
ccache -M 20G

2. 编译指定模块

整个内核是由一个初始化模块程序initrd.img,内核可执行程序vmlinuz和这么多动态库ko文件组成。Linux在启动时可以动态选择需要的库来进行加载,这样可以提升内核的启动效率。另外,将模块编译成动态库(ko文件),在进行自定义模块功能时,也可以只用编译单个模块的代码,也更便利。模块是否编译,是编译进内核镜像还是单独生成内核模块文件ko文件,这些都是在.config文件中配置的。

2.1. 配置文件介绍

2.1.1. .config文件

哪些模块编译进主内核模块,哪些模块单独作为动态库存在。这些都是通过一个配置文件.config来描述的。.config文件中有记录一些配置名,一些配置的大小,剩余的主要是描述是描述是否编译进内核文件,是否编译为单独的模块。如:

# m表示编译成单独的动态库ko文件
CONFIG_ACPI_SBS=m
# y表示编译进内核文件
CONFIG_ACPI_HED=y
# 如果没有配置则表示不编译或者配置为n
CONFIG_ACPI_HED=n

2.1.2. Kconfig文件

哪些字段可以配置,可以匹配什么样的值,默认配置的值是什么等,这些准备信息都是记录kconfig文件中。
Kconfig文件有基本的语法要求:

  config TMPFS_POSIX_ACL
    bool "Tmpfs POSIX Access Control Lists"
    depends on TMPFS
    select GENERIC_ACL
    help
      POSIX Access Control Lists (ACLs) support permissions for users and
      groups beyond the owner/group/world scheme.
      To learn more about Access Control Lists, visit the POSIX ACLs for
      Linux website <http://acl.bestbits.at/>.
     If you don't know what Access Control Lists are, say N.

config是关键字,指定后面的内容为.config文件中的可配置字段名,.config文件中实际使用时会加上CFONFIG_。
bool是描述此字段的类型。Kconfig支持的类型有:bool、tristate、string、hex和int。
● bool类型取值:y或n
● trisate类型取值:y,n或m(三态值,y表示安装进内核,n表示不安装,m表示以模块安装)
● string类型取值:字符串
● hex类型取值:十六进制数字
● int类型取值:十进制数字
bool后面的字符串表示提示信息,在配置界面中显示的。
depends on表示此模块依赖于TMPFS模块,只有TMPFS模块被选中时,此配置信息才可以设置。
select表示此模块被选中时,GENERIC_ACL也会被选中。
help下面的是帮助信息。
详细说明见:Documentation/kbuild/kconfig-language.rst

2.1.3. menuconfig

参考Kconfig文件来配置.config文件,可以完成Kernel的编译配置,但是此方法不够直观,效率不高。make menuconfig可以根据arch/目录下不同架构下的Kconfig和.config文件生成一个菜单窗口,更直观的配置有关信息。
在这里插入图片描述

Kconfig中的bool类型在menucofig中对应[],有[]表示选中,[]表示不选中。
Kconfig中的tristate类型在menuconfig中应对<>,<
>表示选中编译进内核,表示以模块化编译,<>表示不编译。
配置完成之后,可以保存为.config文件。

2.1.4. xconfig

menuconfig是字符终端,依然不够直观,xconfig是基于xWindow的UI窗口终端,更清晰直观。 其功能和menuconfig一样的。

2.1.5. oldconfig

当.config有修改时,调用make oldconfig来验证相关修改是否匹配正确,会自动修改。

2.1.6. defcofig

内核源代码目录中的arch/下有不同架构cpu下的defconfig文件仅参考配置。

2.2. 配置指定模块

有些模块已经配置为编译为ko文件,有些模块没有配置。查看kconfig文件,找出该模块是否可以编译为模块,是否有依赖模块,有则选中,然后在.config中将指定模块配置为CONFIG_XX=m。

2.3. 完整编译

首次使用时,需要完整编译。

2.4. 单独编译

内核模块的makefile中有提供相关方法:

$(MAKE) -C ( K D I R ) M = (KDIR) M= (KDIR)M=(PWD) modules

KDIR为内核顶层目录。
PWD为指定编译模块的目录。
例如:

cd /home/michael/work/Kernel/linux-5.17.12
sudo make -C CONFIG_JBD2=m ./ M=fs/jbd2 modules

2.5. 拷贝

拷贝编译的模块到指定目录

sudo cp jbd2.ko /lib/modules/5.17.12/kernel/fs/jbd2

2.6. 更新驱动信息

sudo depmod-a
# 将变化的驱动信息更新到相关文件中.

2.7. 加载驱动

modprobe jbd2,动态加载驱动,如果jbd2有依赖驱动,会先加载依赖驱动再加载此驱动。
insmod jbd2,只加载此驱动,如果有依赖驱动会加载失败。

3. 制作deb安装文件

3.1. deb-pkg

上面的编译安装方便比较麻烦,如果想部署多台电脑时更不方便。如果能够制作安装包进行部署升级会更方便。
make deb-pkg
上面的命令即可以完成编译并生成deb安装文件存放在上级目录,有三个安装文件,分别为头文件,镜像文件以及libc开发文件,头文件和libc安装包都是用来进行应用程序开发的,可以不用安装。

linux-headers-5.17.12_5.17.12-1_amd64.deb
linux-image-5.17.12_5.17.12-1_amd64.deb
linux-libc-dev_5.17.12-1_amd64.deb

然后可以使用如下命令安装升级重启。

sudo dpkg -i *.deb
sudo update-grub 
sudo reboot

3.2. make-kpkg

make-kpkg也是编译并生成deb安装文件,并且可以修改版本号等操作。

  1. 首先要安装make-kpkg
sudo apt install kernel-package
  1. 开始
sudo make-kpkg  --initrd --append-to-version -20220228  --revision 001 kernel_image kernel_headers -j4

参数说明:
–initrd: 生成initramfs
–append-to-version:生成内核版本附加信息
–revision:deb文件的版本信息,只影响文件名
kernel_image:内核和模块的安装包
kernel_headers:生成内核头文件的安装包。
-j:指定多少个线程编译内核
3. 安装

sudo dpkg -i *.deb
sudo update-grub 
sudo reboot
编译 Ubuntu 20.04 内核的步骤如下: 1. 获取内核代码 可以从 Ubuntu 的官方网站上下载内核代码,或使用 Git 从内核代码仓库中下载。在终端中输入以下命令: ``` sudo apt-get update sudo apt-get install git git clone git://kernel.ubuntu.com/ubuntu/ubuntu-focal.git ``` 2. 安装编译工具 编译 Ubuntu 内核需要安装一些编译工具和依赖项。在终端中输入以下命令: ``` sudo apt-get install build-essential libncurses-dev bison flex libssl-dev libelf-dev ``` 3. 配置内核 进入 Ubuntu 内核代码目录并运行以下命令: ``` cd ubuntu-focal cp /boot/config-$(uname -r) .config sudo make oldconfig ``` 在运行 `sudo make oldconfig` 命令时,系统会提示你是否需要更改一些内核配置。如果你不确定,请保持默认设置。 4. 编译内核 在终端中输入以下命令开始编译内核: ``` sudo make -j $(nproc) ``` 这将使用系统上可用的所有处理器核心进行编译编译过程可能需要一些时间,具体时间取决于你的硬件配置和内核大小。 5. 安装内核 编译完成后,可以安装内核。在终端中输入以下命令: ``` sudo make modules_install sudo make install ``` 这将安装编译后的内核和模块。然后你需要更新 GRUB 配置以便引导新内核。在终端中输入以下命令: ``` sudo update-grub ``` 6. 重启系统 内核安装完成后,重启系统以使新内核生效。 ``` sudo reboot ``` 注意:编译和安装内核可能会导致系统出现问题,因此在执行此操作之前,最好进行全面备份。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值