ARM嵌入式学习(十八)--- Linux的内核编译和启动

目录

一、Linux操作系统概述

1.操作系统

2.Linux内核组成

3.Linux设备驱动与整个软硬件系统的关系

二、Linux内核启动流程解释

1、整体架构

2、Bootloader(以U-Boot为例)

初始化阶段

3、Kernel(操作系统核心)

内核启动最后阶段

4、根文件系统(Rootfs)

三、Linux内核启动流程示例

1.整体框架

2.第一步:搬移内核(kernel)到内存

部分uboot命令解释:

3.第二步:挂载根文件系统(rootfs)

各参数详解

[1. root=/dev/nfs](#1. root=/dev/nfs)

[2. nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3](#2. nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3)

[3. ip=192.168.1.123](#3. ip=192.168.1.123)

[4. console=ttymxc0,115200](#4. console=ttymxc0,115200)

[5. init=/linuxrcroot](#5. init=/linuxrcroot)

整个命令的作用流程

注意:

4.第三步:启动内核

四、内核编译操作示例

[1.将内核源码包拷贝到 Ubuntu 下,并解压到工作目录:](#1.将内核源码包拷贝到 Ubuntu 下,并解压到工作目录:)

2.向内核新增文件(以向drivers/char目录下新增demo.c为例):

3.内核编译流程(所有操作均在内核源码的顶层目录下执行):

五、总结和补充

[1.Kconfig 文件介绍(以添加 ABC 为例)](#1.Kconfig 文件介绍(以添加 ABC 为例))

关键部分解释

添加位置:不要前后,要中间

如何修改生效

注意事项

2.问题汇总:

[1. make zImage不了](#1. make zImage不了)

2.没有网口使用usb转网口转换器会出现开发板和虚拟机无法ping通

[3.启动内核出现类似no soundscard的报错提示](#3.启动内核出现类似no soundscard的报错提示)


一、Linux操作系统概述

1.操作系统

操作系统可以被看做是一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核。内核的接口被称为系统调用。公用的函数库构建在系统调用接口之上,应用程序可以使用公用函数库,也可以使用系统调用。shell是一种特殊的应用程序,为运行其他应用提供了一个接口。

2.Linux内核组成

Linux内核主要由进程调度(SCHED)、内存管理(MM)、虚拟文件系统(VFS)、网络接口(NET)和进程间通信(IPC)5个子系统组成。

进程调度:进程调度控制系统中的多个进程对CPU的访问。
内存管理:内存管理作用是控制多个进程安全地共享主内存区域。
虚拟文件系统:Linux虚拟文件系统隐藏了各种硬件的具体细节,为所有设备提供了统一的接口。
网络接口:网络接口提供了对各种网络标准的存取和各种网络硬件的支持。
进程间通信:进程间通信支持进程之间的通信。

3.Linux设备驱动与整个软硬件系统的关系

除了网络设备外,字符设备与块设备都被映射到Linux文件系统的文件和目录。通过调用open、read、write、close等即可访问字符设备和块设备。所以这就是Linux的"一切皆是文件"的思想。

Linux块设备有两种访问方法:一种是类似于/dev/sda、/dev/sdb的原始块设备,一种是在块设备上简历FAT、EXT4、BRTFS等文件系统,然后以文件路径的形式进行访问。在Linux中,针对NOR、NAND等提供了独立的内存技术设备(Memory Technology Device,MTD)子系统,其上运行YAFFS2、JFFS2、UBIFS等具备擦除和负载均衡能力的文件系统。针对磁盘或Flash设备的FAT、EXT4、YAFFS2、JFFS2、UBIFS等文件系统定义了文件和目录在存储介质上的组织。而Linux的虚拟机文件系统则统一对它们进行了抽象。

二、Linux内核启动流程解释

从Bootloader到根文件系统

1、整体架构

嵌入式Linux系统通常包含三大核心组件:

  • Bootloader(如U-Boot):引导程序

  • Kernel:操作系统内核

  • Rootfs:根文件系统

存储介质常见组合:

  • SD卡:存放bootloader、kernel、rootfs

  • 8G eMMC:同样存放这三部分

  • 网络启动:通过TFTP服务传输kernel(zImage + dtb)(我们使用这种)

内存大小:512M ,kernel加载地址通常为0x80000000或**0x80800000。**

2、Bootloader(以U-Boot为例)

Bootloader是一个为内核启动准备环境的裸机程序,负责引导内核。其主要工作包括:

初始化阶段

  • 初始化异常向量表

  • 初始化CPU工作模式

  • 初始化栈指针

  • 初始化时钟系统

  • 关看门狗

  • 关闭Cache(数据Cache必须关闭,指令Cache可选)

  • 关闭MMU

  • 关闭中断

  • 初始化内存

  • 初始化相关设备(串口、网口)

  • 集成相关协议

  • 搬移内核到内存 --- 向内核传参(根文件系统类型、init进程、控制台)

  • 引导内核启动 --- bootload不再控制CPU,CPU控制权移交给内核

3、Kernel(操作系统核心)

内核是一个庞大而复杂的程序,负责管理整个系统的软硬件资源。主要功能模块:

  • 文件管理:虚拟文件系统(VFS),支持多种文件系统

  • 进程管理:进程创建、调度、终止

  • 网络管理:TCP/IP协议栈

  • 设备管理:驱动程序框架

  • 内存管理:虚拟内存、页表、MMU管理

  • IPC进程间通信:管道、消息队列、共享内存、信号量等

内核启动最后阶段

内核启动到最后,会加载(挂载)根文件系统 ,然后启动第一个用户态进程------init进程

内核通过exec系统调用启动init进程,之后init进程会依次启动其他进程 → 启动shell → 最终运行用户应用程序(userapp)。

4、根文件系统(Rootfs)

根文件系统是第一个挂载的文件系统,它是所有文件的集合,包括:

  • 配置文件 :如/etc/inittab/etc/fstab

  • 系统命令lscatmount等Busybox工具

  • 库文件 :动态链接库(libc.sold-linux.so

  • 用户程序:自定义应用程序

  • 普通文件:文本、mp3、jpg等数据文件

根文件系统为系统提供了最基础的目录结构和运行环境。常见的根文件系统类型有:ext4、yaffs2、jffs2、ubifs、initramfs等。

三、Linux内核启动流程示例

1.整体框架

系统上电根据启动模式配置引脚从不同的介质加载bootloader(以SD卡为例)

1. cpu拷贝bootloader前半部分到OCRAM, bootloader在前半部分代码中初始化好内存,并搬移自己后半部分到内存中执行,bootloader执行到最后阶段搬移内核到内存,并引导内核启动

2-1 内核在SD卡中,则bootloader需要在代码中初始化好SD卡,然后读SD的kernel分区写入内存(忽略)

2-2 内核在ubuntu上,则bootloader需要在代码中初始化有线网卡及集成tftp协议,通过tftp协议下载内核到内存

3-1 根文件系统如果在SD卡中,则内核直接挂载SD卡的rootfs分区(忽略)

3-2 根文件系统在ubuntu上,则内核应该通过nfs挂载ubuntu上的rootfs目录(bootloader向内核传参是应该包含内核启动阶段使用的ip)

2.第一步:搬移内核(kernel)到内存

首先将我们编写好的zImage及xxx.dtb拷贝到tftp服务目录下(tftp服务如何配置上网搜索)

然后打开开发板终端到uboot命令下: 开发板上电后倒计时为0之前按回车键进入uboot命令行

tftp 0x80800000 zImagetftp下载,将zImage下载到内存的0x80800000地址处

tftp 0x83000000 pt.dtb tftp下载,将pt.dtb下载到内存的0x83000000地址处

部分uboot命令解释:

help/? 帮助

printenv 查看环境变量

setenv ipaddr 192.168.1.122 设置环境变量

setenv ipaddr 删除环境变量

saveenv 保存环境变量

ping 网络测试

tftp tftp下载

3.第二步:挂载根文件系统(rootfs)

输入下面命令即可

setenv bootargs root=/dev/nfs nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3 ip=192.168.1.123 console=ttymxc0,115200 init=/linuxrcroot

各参数详解

1. root=/dev/nfs
  • 告诉内核:根文件系统(root filesystem)不在本地块设备(如 SD卡、eMMC),而是通过 NFS(网络文件系统) 提供。

  • /dev/nfs 是一个虚拟设备,专门用于 NFS 根文件系统挂载。

2. nfsroot=192.168.1.3:/home/linux/nfs/imx6/rootfs,nfsvers=3
  • 192.168.1.3:NFS 服务器 IP 地址(通常是开发主机或服务器)。

  • /home/linux/nfs/imx6/rootfs:服务器上导出的 NFS 共享目录路径(即根文件系统的内容所在位置)。

  • nfsvers=3:指定使用 NFS 协议版本 3。版本 3 相比版本 2 支持更大的文件、异步写入等,且无需端口映射器(portmap)的复杂依赖。

3. ip=192.168.1.123
  • 配置开发板(目标机)的 IP 地址为 192.168.1.123

  • 若需同时指定服务器 IP、网关、子网掩码等,可使用完整格式:
    ip=192.168.1.123:192.168.1.3:192.168.1.1:255.255.255.0::eth0:off

    但此处简写只设置了客户端 IP,内核会自动通过 DHCP 或 Bootp 获取其余信息(若服务器支持)。

4. console=ttymxc0,115200
  • ttymxc0:串口设备名(i.MX6 系列 SoC 的第一个 UART 接口)。

  • 115200:波特率。

  • 内核启动信息以及后续的 init 进程的标准输入/输出都会重定向到这个串口,方便调试。

5. init=/linuxrcroot
  • init进程,根文件挂载完成后启动的第一个进程(1号进程:linuxrcroot)

整个命令的作用流程

  1. U-Boot 启动后,将 bootargs 传递给内核。

  2. 内核解析参数:

    • 根据 ip=... 配置网卡 IP。

    • 根据 nfsroot=... 尝试挂载 NFS 共享目录作为根文件系统。

    • 挂载成功后,根据 console=... 将控制台输出到串口。

    • 最后执行 init=... 指定的用户态程序

  3. 如果一切正常,开发板就从 NFS 启动,无需烧写根文件系统到本地存储------非常适合开发阶段频繁修改文件系统的场景。

注意:

  • 网络连通性 :开发板必须能 ping 通 NFS 服务器(192.168.1.3),且服务器需正确配置 NFS 导出(/etc/exports)。

  • NFS 服务 :服务器上要安装并启动 NFS 服务(如 nfs-kernel-server),且导出的目录权限允许开发板访问(通常设置 rw,no_root_squash,sync)。

  • 内核配置 :内核需编译支持 NFS 根文件系统(CONFIG_ROOT_NFS=yCONFIG_NFS_FS=y)。

4.第三步:启动内核

bootz 0x80800000 - 0x83000000 启动0x80800000地址处的内核

四、内核编译操作示例

这一部分主要讲的是如何编译内核,上面部分是启动已经编译好了的内核。

内核编译是将内核源码转换成可运行的镜像文件(zImage)和设备树文件(dtb)的过程。本章详细介绍内核编译的完整流程,包括配置、编译以及向内核添加自定义驱动。

1.将内核源码包拷贝到 Ubuntu 下,并解压到工作目录:

linux官网上下载一个内核源码包(要找对应的开发板的内核源码包,比如我这里是imx6ull):

复制代码
tar -xvf linux-imx-xxx.tar.bz2
cd linux-imx-xxx

2.向内核新增文件(以向drivers/char目录下新增demo.c为例):

1. 在drivers/char目录下创建并编辑demo.c

2. 修改同层目录下的Makefile新增一行 obj-$(CONFIG_DEMO) += demo.o

3. 修改同层目录下的Kconfig文件,新增一个DEMO的配置

4. make menuconfig(在 里面查看我们新增的驱动是否生效)

5. make zImage -j20(编译内核)

3.内核编译流程(所有操作均在内核源码的顶层目录下执行):

1. 拷贝默认配置到.config cp arch/arm/configs/imx_alientek_emmc_defconfig .config

2. make menuconfig 内核配置(选择编译的模块)

3. make zImage 编译内核(仅生成zImage)

make dtbs 编译设备树(生成dtb文件)

make 全编译 -jn 多线程编译 n代表线程数,比如-j20

arch/arm/boot/zImage

arch/arm/boot/dts/imx6ull-alientek-emmc.dtb

五、总结和补充

1.Kconfig 文件介绍(以添加 ABC 为例)

Kconfig 是 Linux 内核(以及许多嵌入式系统如 U-Boot、Buildroot)中用于配置系统的脚本语言文件。它定义了配置选项的层次结构、类型、默认值和帮助信息,最终通过 menuconfignconfig 等工具生成 .config 文件,控制哪些功能被编译进内核或模块。

这里以添加的ABC为例:

关键部分解释
  • config ABC

    定义配置选项的名称,最终会生成 CONFIG_ABC 的宏。
    命名建议:大写字母,通常与功能相关。

  • bool "ABC support"

    类型为布尔型(bool),只有两种值:y(编译进内核)或 n(不编译)。
    引号内的字符串是菜单中显示的名称

    其他类型还包括:tristate(三态:y/m/n)、inthexstring 等。

  • default y

    默认值为 y。即不手动修改时,该选项会被选中。

    可以省略,默认值为 n。也可以根据其他选项条件默认,如 default y if XYZ

  • help

    帮助文本,详细解释该选项的作用。用户按 ?h 时会显示。

    必须以缩进(通常是 tab 或空格)书写,直到下一个非缩进行为止。

添加位置:不要前后,要中间

在 Kconfig 文件中,选项的顺序会影响 menuconfig 的显示顺序。用户强调 添加 config 不要在前面和后面,最后是中间,意思是:

  • 不要加在文件开头(可能会破坏依赖关系或默认菜单结构)。

  • 不要加在文件末尾(末尾可能属于某个 menu/endmenu 之外,或影响整体层级)。

  • 加在中间合适的位置 :通常是按功能分类,放在与 ABC 功能相关的 menuif 块内,或与其他同类选项一起。

如何修改生效

  1. 编辑对应目录下的 Kconfig 文件(如 drivers/Kconfig 或新建子目录的 Kconfig)。

  2. 在合适位置(已有选项之间)添加 config ABC 块。

  3. 运行 make menuconfig,即可看到新选项。

  4. 保存配置后,.config 中会出现 CONFIG_ABC=y

注意事项

  • 如果希望 ABC 只在某个条件成立时才可见,可以用 depends onif。例如:

  • 如果希望 ABC 直接修改其他配置(如自动选中另一个选项),可以用 select XYZ

  • 布尔选项的显示结果:[*] 表示 y[ ] 表示 n

deponds on(弱依赖),要选择依赖里面的模块编译,才能选择这个模块是否编译

select(强依赖) ABC 如果选择了ABC1则一定会把ABC也一起选了

source 相当于include ,把kconfig里面的东西直接放到写source这个位置

2.问题汇总:

1. make zImage不了

解决办法:没装lzop:sudo apt install lzop 或者 终端窗口不够大也会报错,尽量把窗口放大make

2.没有网口使用usb转网口转换器会出现开发板和虚拟机无法ping通

解决办法:检查虚拟机是否把usb连接上了,这个转换器必须连接到主机。以及没有网口无法使用双网卡

3.启动内核出现类似no soundscard的报错提示

解决办法:根文件系统的挂载路径有问题,检查一下命令的路径和实际的路径是否一致

相关推荐
星幻元宇VR2 小时前
VR旋转蛋椅:沉浸式安全科普新体验
科技·学习·安全·vr·虚拟现实
魔都吴所谓2 小时前
【Ubuntu】离线环境下Git LFS(deb包)安装与验证完整教程
linux·git·ubuntu
Learn-Python2 小时前
修改docker容器内文件后让其生效
运维·docker·容器
w6100104662 小时前
CKA-2026-StorageClass
linux·运维·服务器·cka·storageclass
ZhiqianXia2 小时前
PyTorch 学习笔记(12):ATen C++ 算子引擎的完整架构之旅
pytorch·笔记·学习
旖-旎2 小时前
链表(两两交换链表中的节点)(2)
数据结构·c++·学习·算法·链表·力控
Meaauf2 小时前
VMware五种网络模式详解与EVE-NG互联指南
运维·服务器·网络
吕司2 小时前
Linux线程同步
linux·服务器·开发语言
桦02 小时前
[Linux复习]:网络
linux·运维·网络