文章目录
一、Ubuntu内核编译1.1 为什么自己编译内核1.2 Ubuntu 内核源码下载1.21 内核的作用1.22 Linux内核与ubuntu内核1.23 Ubuntu内核源码仓库 1.3 编译ubuntu内核1.31 看看系统的已有内核1.32 编译新的内核 二、镜像制作
一、Ubuntu内核编译
1.1 为什么自己编译内核
一个Linux发行版比如ubuntu、centos,有自己对应的内核,比如Ubuntu20.04的内核,这些Linux发行版的内核则又是以Linux内核为基础进行定制开发的。
通常说的“内核编译”,可以是编译Linux内核,也可以是编译定制化的Linux内核,比如ubuntu22.04的内核。无果我们使用的是ubuntu,那么最好编译ubuntu内核代码(已经定制化的Linux内核代码),而不是编译Linux内核代码,以免出现潜在的冲突。
一般来说,Linux发行版都有自己默认的Linux内核或者说“定制化的Linux内核”,它们已经优化地很好了。为什么我们还要自己去变编译一遍呢?
的确,对于大多数普通用户来说,直接使用操作系统默认提供的内核以及通过包管理器进行更新通常是最稳妥和方便的选择。默认提供的内核由发行版的维护者经过仔细测试和配置,确保与操作系统的其他组件兼容,同时也包含了一些针对安全性和稳定性的补丁。
内核编译的主要优势体现在一些特殊需求的场景,例如:
特定硬件或嵌入式系统: 在一些特殊的硬件平台或嵌入式系统中,可能需要根据具体硬件配置进行内核的定制和编译。功能和性能优化: 对于高度专业化或性能敏感的场景,你可能希望调整内核配置以满足特定需求,或者应用一些优化。最新功能和实验性特性: 如果你想尝试最新的 Linux 内核功能或实验性特性,而发行版的默认内核版本较老,那么编译新的内核版本可能是一个选择。对于绝大多数桌面和服务器使用,使用发行版默认的内核,并通过包管理器进行更新,是保持系统稳定性和安全性的最佳方式。内核编译更多地适用于那些对系统定制有深入需求的用户,对内核有深入了解的开发者,或者一些专业领域的使用场景。
也就是说:编译内核是对已经定制化的Linux内核进行进一步地定制化,使得其在当前的硬件上得到最大的优化。 (比如ubuntu22.04这个系统,很多设备都可以安装,但他的内核配置并不一定能发挥你的硬件的最大性能)
通常,Linux内核的每个大版本都会进行维护和更新,比如5.4.0-xxx,那么Ubuntu(LTS版本)这些发行版的内核也会对应进行更新。我们常用的apt upgrade
命令,就包括这一更新。注意这和编译内核的重构操作不同。ubuntu某一个版本,比如ubuntu22.04,只会对某一个Linux内核的大版本有最好的适配(见1.23节),你如果编译内核的时候,换了另一个大版本的内核源代码,则可能会有新的适配冲突。
内核编译,只是对当前操作系统的内核进行的定制化操作。如过要对内核进行定制化编译,还要默认安装一个开发环境,做一个操作系统镜像给别人安装,则还设计操作系统镜像制作的内容,见本文第二节。
1.2 Ubuntu 内核源码下载
1.21 内核的作用
操作系统内核是计算机系统中的核心,它负责管理系统的资源、提供各种服务,以及实现用户和硬件之间的通信。以下是内核的一些主要作用:
资源管理: 内核负责管理计算机系统的各种硬件资源,包括CPU、内存、硬盘、网络接口等。它通过调度算法来决定哪个进程(或任务)在某个时刻执行,以及如何分配和释放内存。进程管理: 内核负责创建、终止和调度进程。它管理进程的状态转换,分配资源,以及协调不同进程之间的通信和同步。文件系统管理: 内核提供文件系统接口,使得应用程序可以通过文件系统进行文件的读取、写入和管理。它还负责处理文件和目录的访问权限、文件锁定等问题。设备驱动程序: 内核包含设备驱动程序,用于与硬件设备进行通信。这些驱动程序允许操作系统与硬件之间进行有效的交互,包括输入输出设备、网络接口、磁盘驱动器等。系统调用接口: 内核提供了系统调用接口,允许应用程序通过一组标准化的接口与内核进行通信。这些接口包括对文件、进程、网络等的访问。内存管理: 内核负责管理系统的物理内存和虚拟内存。它通过分页机制、内存映射等方式来实现进程间的内存隔离和保护。中断处理: 内核负责处理硬件和软件产生的中断。硬件中断可以来自于设备的状态变化,而软件中断通常是由系统调用或异常引起的。内核需要适时地响应这些中断以确保系统正常运行。安全性和权限控制: 内核实施对系统资源的访问控制,确保只有经过授权的进程才能够执行敏感操作。这包括用户身份验证、访问权限检查等功能。总体而言,内核是操作系统的核心,它为上层应用程序提供了一个抽象的接口,使得开发者可以专注于应用程序的逻辑而不用直接处理底层硬件和资源管理的细节。内核的设计和性能直接影响整个操作系统的稳定性和效率。
1.22 Linux内核与ubuntu内核
Linux 内核是整个操作系统的核心,Ubuntu 内核是为 Ubuntu 操作系统进行定制的 Linux 内核,而 Ubuntu 系统是包含了 Linux 内核和其他软件的完整操作系统。在使用 Ubuntu 操作系统时,你直接与 Ubuntu 系统进行交互,而 Ubuntu 系统的核心是 Ubuntu 内核,而 Ubuntu 内核的核心是 Linux 内核。
Linux 内核:Linux 内核是操作系统的核心组件,是负责管理系统硬件和提供基本系统服务的软件。它是由 Linus Torvalds 在1991年首次发布的,并经过多年的发展,成为一个开源的、免费的内核。Linux 内核在计算机科学领域中广泛应用,作为许多操作系统的核心,包括 Ubuntu。Ubuntu 内核:
Ubuntu 是一个基于 Linux 内核的开源操作系统。Ubuntu 是由 Canonical 公司维护的一个 Linux 发行版,它构建在 Linux 内核的基础上,并包括了来自不同开源项目的软件包和工具。Ubuntu 内核实际上就是 Linux 内核,但经过了一些定制和配置,以适应 Ubuntu 操作系统的特定需求。Ubuntu 内核通常是 Ubuntu 操作系统的一个组成部分。Ubuntu 系统:
Ubuntu 系统是指完整的 Ubuntu 操作系统,包括 Linux 内核、GNU 工具和其他开源软件。这个操作系统提供了一个完整的用户环境,包括桌面环境(如 GNOME、KDE)和许多应用程序。Ubuntu 系统基于 Debian 发行版,是一个用户友好、稳定且广泛使用的 Linux 操作系统。
Linux内核官方的源代码仓库:https://www.kernel.org/
Additional: 查询你的Ubuntu版本信息 uname -a
root@CQUPTLEI:~# uname -aLinux CQUPTLEI 5.4.0-169-generic #187-Ubuntu SMP Thu Nov 23 14:52:28 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
我服务器Linux内核版本是 5.4.0-169,这是2023年12月23日的一个更新。
1.23 Ubuntu内核源码仓库
Ubuntu Kernel Repositories:https://kernel.ubuntu.com/git/
这是ubuntu内核的git仓库列表。
近几年Ubuntu版本对应的Linux内核版本及名称(codename):红色是LTS版本(目前)
Ubuntu版本 | 内核版本 | 代号 |
---|---|---|
16.04 | 4.4 | Xenial Xerus |
16.10 | 4.8 | Yakkety Yak |
17.04 | 4.10 | Zesty Zapus |
17.10 | 4.13 | Artful Aardvark |
18.04 | 4.15 | Bionic Beaver |
18.10 | 4.18 | Cosmic Cuttlefish |
19.04 | 5.0 | Disco Dingo |
19.10 | 5.3 | Eoan Ermine |
20.04 | 5.4 | Focal Fossa |
20.10 | 5.8 | Groovy Gorilla |
21.04 | 5.11 | Hirsute Hippo |
21.10 | 5.13 | Impish Indri |
22.04 | 5.15 | Jammy Jellyfish |
22.10 | 5.19 | Karmic Koala |
23.04 | 6.2 | Luminous Lorikeet |
23.10 | 6.5 | Mystic Mongoose |
Ubuntu的版本号命名规则是根据正式版发布的年月命名,其中X表示年份(减去2000),YY表示发布的月份。例如,Ubuntu 16.04意味着2016年4月发布的Ubuntu,Ubuntu 22.10意味着2022年10月发布的Ubuntu1。因此,Ubuntu的版本号通常以.xx.04或.xx.10结尾。
前面的ubuntu内核仓库的source选项下有很多版本,对应不同的平台或特性:
Linux内核版本 | 用途 |
---|---|
linux-unstable | 该内核版本是Linux内核的开发版本,用于测试新功能和修复错误。 |
linux | 该内核版本是Linux内核的稳定版本,用于大多数Linux发行版。 |
linux-lowlatency | 该内核版本是Linux内核的低延迟版本,用于音频和其他实时应用。 |
linux-raspi | 该内核版本是专门为树莓派设计的Linux内核版本。 |
linux-aws | 该内核版本是专门为Amazon Web Services(AWS)设计的Linux内核版本。 |
linux-azure | 该内核版本是专门为Microsoft Azure云服务设计的Linux内核版本。 |
linux-gcp | 该内核版本是专门为Google Cloud Platform(GCP)设计的Linux内核版本。 |
linux-ibm | 该内核版本是专门为IBM Power Systems设计的Linux内核版本。 |
linux-oracle | 该内核版本是专门为Oracle Linux设计的Linux内核版本。 |
linux-riscv | 该内核版本是专门为RISC-V架构设计的Linux内核版本。 |
linux-starfive | 该内核版本是专门为StarFive处理器设计的Linux内核版本。 |
linux-laptop | 该内核版本是专门为笔记本电脑设计的Linux内核版本。 |
linux-intel-opt | 该内核版本是专门为英特尔处理器设计的Linux内核版本。 |
linux-nvidia | 该内核版本是专门为NVIDIA GPU设计的Linux内核版本。 |
1.3 编译ubuntu内核
1.31 看看系统的已有内核
编译内核后,生成的文件通常存储在相应的构建目录中。以下是一些常见的生成文件和目录:
内核映像: 编译后的内核映像通常是 vmlinuz 或 bzImage,位于源代码目录的 arch/<架构>/boot/ 目录下。例如,在x86_64架构上,可能是 arch/x86/boot/bzImage。
模块: 内核模块会被编译到 modules 目录中,通常位于源代码目录的 kernel 子目录下。例如,kernel/drivers/net/wireless/。
initramfs: 初始内存文件系统(init ram fs)通常会生成在 /boot 目录中,例如 initrd.img-<kernel_version>。
System.map: System.map 文件包含了内核符号和地址的映射关系。在源代码目录中的 arch/<架构>/boot/ 目录下,例如 arch/x86/boot/System.map。
配置文件: 内核的配置文件通常是 .config,位于源代码目录。这个文件记录了内核的配置选项。
构建日志: 构建期间的日志文件通常存储在 ./debian/build/build-/ 目录中。
其他文件: 构建过程可能还生成其他一些文件,具体取决于内核配置选项和构建过程中使用的工具。
具体的路径和文件名可能会根据你的内核配置、版本和使用的工具而有所不同。在编译过程中,你可以在终端上看到输出,其中包含有关生成文件的详细信息。
当你安装新的内核时,生成的内核映像和相关文件将被复制到 /boot
目录,并通过 GRUB
或其他引导加载程序进行配置,以便在系统启动时选择新的内核。
以下是 /boot
目录下一些常见的文件和它们的作用:
文件/目录 | 作用 |
---|---|
vmlinuz-<kernel_version> | 内核映像文件,包含操作系统内核的可执行文件。 |
initrd.img-<kernel_version> | 初始内存文件系统(initramfs),用于在系统引导时加载必要的模块。 |
System.map-<kernel_version> | 包含内核符号和地址的映射关系。 |
config-<kernel_version> | 内核的配置文件,记录了编译时的配置选项。 |
abi-<kernel_version> | 用于定义二进制接口的文件。 |
grub/ | 存储 GRUB 引导加载程序的相关文件。 |
efi/ | 存储 EFI 引导加载程序的相关文件(如果系统使用 UEFI)。 |
lost+found/ | 用于存储文件系统恢复过程中找到的损坏的文件和目录。 |
这些文件和目录在 /boot
中存储了与引导和内核相关的信息。它们是系统引导过程中所需的关键组件,包括操作系统内核、引导加载程序配置文件等。
我的服务器:
每个条目的含义:
config-5.4.0-149-generic
、config-5.4.0-152-generic
、config-5.4.0-169-generic
: 这些是与特定内核版本相关的内核配置文件。它们包含了编译内核时使用的配置选项。 initrd.img-5.4.0-149-generic
、initrd.img-5.4.0-152-generic
、initrd.img-5.4.0-169-generic
: 这些是与相应内核版本关联的初始内存文件系统(initramfs)。它们包含在引导时加载的文件和模块,以便于启动系统。 System.map-5.4.0-149-generic
、System.map-5.4.0-152-generic
、System.map-5.4.0-169-generic
: 这些文件包含了内核符号和地址的映射关系,有助于调试内核问题。 vmlinuz-5.4.0-149-generic
、vmlinuz-5.4.0-152-generic
、vmlinuz-5.4.0-169-generic
: 这些是相应内核版本的 Linux 内核可执行文件。 grub
: 这是一个目录,通常包含 GRUB 引导加载程序的相关文件。 memtest86+.bin
、memtest86+.elf
、memtest86+_multiboot.bin
: 这些是内存测试工具 Memtest86+ 的二进制文件,用于检测系统内存的问题。 vmlinuz
、vmlinuz.old
: 这些是当前使用的和之前使用的 Linux 内核的符号链接。通常,vmlinuz
指向最新的内核版本,而 vmlinuz.old
指向上一个使用的内核版本。 此外:/lib/modules
目录包含内核模块,这些模块是内核的一部分,但不是内核本身。这些模块通常由内核启动时自动加载,以便内核可以与硬件设备进行交互。一个内核版本对应一个文件夹,文件夹的个数大于等于/boot目录下的内核版本数(boot 下是已安装且能启动的内核)。
如过要指定系统使用某个版本的内核(已经安装在/boot目录下的):
可以编辑/etc/default/grub
文件,编辑这个文件会更新/boot目录下的grub/文件夹下的相关配置文件。这是为了便于编辑、维护和安全,和crontab
是类似的。
我用vim编辑: vim /etc/default/grub
在文件中找到 GRUB_DEFAULT
行,并将其值更改为所需的内核版本的菜单条目的索引。GRUB 菜单的第一个内核版本索引为 0,第二个为 1,以此类推。
查看已安装且能启动的内核:grep -oP "menuentry '\K[^']+" /boot/grub/grub.cfg
GRUB 菜单中的索引 0 对应着 “Ubuntu” 条目,这是一个默认的启动项,通常对应着默认的内核版本。由于没有指定具体的内核版本号,这可能是系统当前默认的启动选项,对应着 GRUB 菜单中的第一个条目。
我的 /etc/default/grub
文件中GRUB_DEFAULT=1,也即Ubuntu, with Linux 5.4.0-169-generic
。
使用:uname -r
可以看到系统当前使用的内核,的确如此:
root@CQUPTLEI:/boot# uname -r5.4.0-169-generic
1.32 编译新的内核
(1)准备工作
安装 build-essential 和其他一些编译工具。在 Ubuntu 系统中,你可以运行以下命令来安装:
sudo apt-get updatesudo apt-get install build-essential kernel-package libncurses5-dev bison flex libssl-dev
(2)获取内核源代码
默认情况下,Ubuntu 发行版通常不会包含完整的 Linux 内核源代码。Ubuntu 使用预编译的内核二进制包来简化用户的安装和升级过程。如果你想要编译内核或者对内核进行修改,你需要手动下载内核源代码。
这里下载Ubuntu20.04(查看Ubuntu版本:lsb_release -a
)的最新内核代码,前面已经说了网址。选择focal linux那一行:
点repo就会看到类似:
Get this repository:git clone https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/focal
自己建一个目录,克隆源码就可以了。下载内容大概2GB。
(3)