如何编译Linux内核源码?

如何编译并运行Linux系统?

前言

学习Linux内核是一件振奋人心的事情,而在学习伊始对Linux内核的成功编译并运行也更会燃起更足的动力去钻研。本文从下载并编译Linux内核、编译busybox、制作一个最小的根文件系统,最后用qemu启动你编译好的内核和根文件系统 ,初步感受Linux内核的魅力所在。

首先明确两点:

  1. 配置内核就是你来决定编码哪些代码;
  2. 编译内核就是生成可执行文件的一个过程。

再明确内核文件的产物名称:

  • vmlinux:原始的,未经压缩的内核可执行文件
  • zImage:压缩过的可执行文件——压缩vmlinux后,加上一个head part(用来解压)
  • uImage:用于给uboot引导的zImage
  • bzImage:即bigzImage ,通过gzip压缩的

好了,明确了上述几点,就可以开始实验了。本文的实验环境如下:

  • Linux系统:ubuntu 20.04
  • linux源码版本:linux-4.9.229
  • busybox源码版本:busybox-1.30.0
  • qemu-system-x86_64版本:2.0.0

实验目标

  1. 编译Linux内核源码
  2. 编译busybox
  3. 制作一个简版文件系统
  4. 制作根文件系统镜像文件
  5. 利用qemu运行linux内核

1.下载并编译Linux内核

Index of /pub/linux/kernel/v4.x/mirrors.edge.kernel.org/pub/linux/kernel/v4.x/

下载并解压后,进入目录。

1.指定硬件体系架构

为了演示方便,选用了x86架构,如果编译arm则需要再下载对应的toolchain。

1
$ export ARCH=x86

2.配置board config

1
$ make  x86_64_defconfig

3.配置内核

这一步其实是对第2步的进行微调,这里我们使用基于ncurse库编制的图形界面工具:

1
$ make menuconfig

如果执行该命令时出现:

vXCMG9.png

原因:缺少ncurses dev工具

1
sudo apt-get install libncurses5-dev

如果需要内核支持ramdisk驱动,需要选中如下配置:

1
2
3
4
5
6
General setup  --->
----> [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
Device Drivers --->
[*] Block devices --->
<*> RAM block device support
(65536) Default RAM disk size (kbytes)

4.编译内核

1
$ make -j8

编译成功后的内核位于:arch/x86_64/boot/bzImage

至此,内核编译完成。

2. 编译busybox

什么是busybox?

busybox号称“嵌入式Linux的瑞士军刀”。BusyBox工具小巧高效,可以替代一大批常用的标准Linux命令行工具,功能有所简化,非常适合资源有限的嵌入式平台。BusyBox是模块化且高度可配置的,可以对其进行裁剪以满足特定需求。

在如下链接下载busybox:

https://busybox.net/downloads/busybox.net/downloads/

我们以busybox-1.30.0作为实验对象。

下载之后解压并进入该busybox目录开始配置并编译。这里把busybox配置为静态编译,这样不依赖其他动态库比较容易操作和演示。编译则似曾相识,与编译内核的指令是一样的!

1
2
3
4
5
$ make menuconfig

Busybox Settings --->
Build Options --->
[*] Build BusyBox as a static binary (no shared libs)

配置完之后进行编译和安装

1
$ make && make install

make是编译busybox,make install是为了在对应目录中编译安装一系列的工具。

编译完成后的busybox就安装在源码根目录下的_install目录了。

至此,我们对Linux内核和busybox进行了配置和编译。光编译肯定不过瘾,接下来演示基于busybox制作一个简单的文件系统,并通过qemu模拟器运行Linux,真正的让内核工作起来!

3. 制作一个简版文件系统

编译完成后的busybox就安装在源码根目录下的_install目录了,我们进入_install目录,补充一些必要的文件或目录,相关的shell命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ mkdir -p etc dev mnt proc sys tmp mnt
$ mkdir -p etc/init.d/

$ mkdir etc dev mnt
$ mkdir -p proc sys tmp mnt
$ mkdir -p etc/init.d/
$ vim etc/fstab
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
$ vim etc/init.d/rcS
echo -e "Welcome to tinyLinux"
/bin/mount -a
echo -e "Remounting the root filesystem"
mount -o remount,rw /
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
$ chmod 755 etc/init.d/rcS
$ vim etc/inittab
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r
$ chmod 755 etc/inittab
$ cd dev
$ sudo mknod console c 5 1
$ sudo mknod null c 1 3
$ sudo mknod tty1 c 4 1

4. 制作根文件系统镜像文件

思路:

  1. 先制作一个空的镜像文件;
  2. 然后把此镜像文件格式化为ext3格式
  3. 接着把此镜像文件挂载,并把根文件系统复制到挂载目录
  4. 卸载该镜像文件。
  5. 打成gzip包。
1
2
3
4
5
6
7
8
9
10
#!/bin/bash
rm -rf rootfs.ext3
rm -rf fs
dd if=/dev/zero of=./rootfs.ext3 bs=1M count=32
mkfs.ext3 rootfs.ext3
mkdir fs
mount -o loop rootfs.ext3 ./fs
cp -rf ./_install/* ./fs
umount ./fs
gzip --best -c rootfs.ext3 > rootfs.img.gz

最终生成的文件系统镜像名字为:rootfs.img.gz

准备好了内核和文件系统镜像,接下来就是见证奇迹的时刻!

5. qemu运行linux内核

1
2
3
4
5
$ qemu-system-x86_64 \
-kernel ./linux-4.9.229/arch/x86_64/boot/bzImage \
-initrd ./busybox-1.30.0/rootfs.img.gz \
-append "root=/dev/ram init=/linuxrc" \
-serial file:output.txt

vXCgIg.png

这样一个完整的Linux系统就起来啦!

-------------本文结束感谢您的阅读-------------

本文标题:如何编译Linux内核源码?

文章作者:孤岛violet

发布时间:2022年09月11日 - 21:49

最后更新:2022年09月11日 - 22:35

原始链接:http://yoursite.com/2022/09/11/Linux-kernel-compilation/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

undefined