Linux系统移植过程(以及Linux系统详解)

1. 简介        

   Linux在嵌入式系统中占据重要地位,其优点包括开源免费、高度可定制、强大的稳定性和安全性,以及广泛的硬件支持和丰富的软件资源。这些特点使得Linux成为嵌入式设备开发的首选操作系统,广泛应用于智能手机、平板电脑、智能家居、工业自动化、网络设备等多个领域。 

Linux系统移植过程:

  1.         配置交叉编译工具链
  2.         bootloader的移植
  3.         内核配置、编译和移植
  4.         制作根文件系统

2. 配置交叉编译工具链

        交叉编译工具链用来在主机上编译应用程序,而这些应用程序是在 ARM 等其他平台上运行。 

选择合适的交叉编译工具链

常见的工具链有:

  • GNU Toolchain for ARM:例如 arm-linux-gnueabihf(适用于 ARM Cortex-A 系列)。
  • Linaro Toolchain:Linaro 提供了针对 ARM 架构优化的 GCC 工具链。
  • Mentor Graphics Sourcery CodeBench:一个面向嵌入式系统的商用工具链,支持多个架构。
  • Buildroot/Yocto 提供的工具链:可以根据特定硬件需求配置和构建。

         设置交叉编译工具主要是设置PATHARCHCROSS_COMPILE三个环境变量

1. PATH环境变量

定义与作用:

  • PATH环境变量主要用于指定系统搜索可执行文件的目录。当你在命令行(如Windows的cmd或Linux的bash)中输入一个命令时,系统会按照PATH环境变量中指定的目录顺序去查找这个命令对应的可执行文件。
  • 通过设置PATH环境变量,用户可以在任意目录下启动应用程序,而无需先切换到应用程序所在的目录。

配置方法:

  • 在Windows系统中,可以通过“系统属性”->“高级”->“环境变量”来配置PATH环境变量。
  • 在Linux系统中,可以通过编辑/etc/profile~/.bashrc等文件来永久配置PATH环境变量,或者通过export命令在当前会话中临时配置。

2. ARCH环境变量

定义与作用(注意:ARCH环境变量并不是在所有系统或场景下都普遍存在,它更多地在特定场景或工具链中被使用):

  • ARCH环境变量通常用于指定目标架构或处理器类型。在跨平台编译或构建系统时,ARCH环境变量可以帮助开发者或构建工具明确目标平台的架构信息。
  • 例如,在嵌入式开发或交叉编译环境中,可能需要设置ARCH环境变量来指示编译工具链生成适用于特定架构的代码。

配置方法:

  • ARCH环境变量的配置方法取决于具体的使用场景和工具链。在某些情况下,它可能需要在构建脚本或命令行中手动设置

3. CROSS_COMPILE环境变量

定义与作用:

  • CROSS_COMPILE环境变量在交叉编译环境中非常重要。它指定了交叉编译工具链的前缀,这个前缀用于标识一系列针对特定目标架构的编译工具(如编译器、汇编器等)。
  • 当在主机上进行交叉编译时,设置CROSS_COMPILE环境变量可以确保构建系统使用正确的工具链来生成目标平台上的可执行文件。

配置方法:

  • CROSS_COMPILE环境变量通常需要在构建脚本或命令行中设置。其值应该是交叉编译工具链前缀的完整路径(可选),后跟工具链的前缀(如arm-linux-gnueabihf-)。

3. bootloader的移植

        BootLoader主要功能是初始化硬件设备引导操作系统内核

        U-Boot(Universal Boot Loader)是BootLoader的一种

        U-Boot(Universal Boot Loader)是一个开源的引导加载程序,主要用于嵌入式系统。它支持多种不同的计算机系统结构和处理器架构,如PPC、ARM、AVR32、MIPS、x86等,并且支持多种嵌入式操作系统,如Linux、Android、NetBSD、VxWorks等。

U-Boot源码主要分为以下几个部分:

arch/:存放与架构相关的代码,如ARM、x86等。
board/:存放与特定开发板相关的代码。
common/:通用代码,包含U-Boot核心功能实现。
configs/:存放各种开发板的配置文件。
drivers/:存放各种外设驱动代码。
include/:头文件目录。
tools/:编译U-Boot时需要使用的工具代码。

1. U-Boot移植步骤:    

    1. 获取源码:从官方或者定制版本的仓库中获取U-Boot的源码。

    2. 工具链准备:确保有正确的交叉编译工具链。例如,对于ARM架构,通常使用arm-none-eabi-gcc或者arm-linux-gnueabi-gcc

        配置开发环境

配置环境变量:设置PATH、ARCH、CROSS_COMPILE等环境变量,以确保编译器和相关工具能正确找到。

export PATH=/path/to/toolchain/bin:$PATH
export ARCH=arm
export CROSS_COMPILE=arm-none-eabi-

        3. 选择开发板配置

        选择合适的配置文件:U-Boot支持许多不同的板卡,每个板卡都有一个对应的配置文件,位于configs/目录中。使用make命令选择合适的配置文件

make <board_name>_defconfig

        4. 修改U-Boot源码(u-boot不断完善,通常情况选择合适的配置文件不需要再修改源码)

  •         设备树和硬件初始化:根据硬件平台的差异,修改相应的设备树文件(位于arch/arm/dts/等目录)和板级初始化代码(通常在board/目录中)。
  •         内存映射和引导地址:根据硬件手册,设置正确的内存映射和引导地址。
  •         驱动支持:如果有定制的硬件接口,可能需要添加或修改U-Boot中的驱动代码。

        5. 编译U-Boot

使用make命令编译U-Boot。

make

编译成功后,生成的二进制文件通常位于u-boot.bin或者u-boot.img

        6. 烧写U-Boot

        烧写到开发板:根据硬件平台的不同,使用JTAG、串口或者SD卡等方式将编译好的U-Boot烧写到开发板。

        7. 测试和调试

  • 启动U-Boot:上电后,观察串口输出,确认U-Boot能够正确启动。
  • 调试:如果U-Boot不能正确启动,可以通过串口输出信息、JTAG等方式进行调试。

        8. 优化和定制

  • 根据需求定制:根据项目需求,进一步优化U-Boot的启动时间、功能以及定制菜单选项等。
  • 添加脚本支持:根据需要,可以在U-Boot中添加特定的启动脚本(如环境变量bootcmd),实现自动化启动。

2. U-boot工作模式

        U-Boot的工作模式主要指其在系统启动过程中的不同阶段和运行方式。

1. 启动模式(Boot Mode)

        U-Boot的启动模式是其最基本的工作模式。在这种模式下,U-Boot负责完成硬件初始化、加载操作系统内核以及启动操作系统。启动模式通常分为以下几种:

  • 从Flash启动:U-Boot从NAND Flash或NOR Flash中被直接加载和执行,这种方式常用于大多数嵌入式系统,因为Flash存储器可以在断电后保存数据。

  • 从SD卡启动:在一些开发板上,U-Boot可以从SD卡启动。通常用于开发和调试,因为SD卡易于插拔和更新。

  • 从网络启动(TFTP Boot):U-Boot支持通过网络从TFTP服务器下载内核镜像并启动。这种方式适合在开发过程中快速更新和测试新内核或文件系统。

  • USB启动:U-Boot可以通过USB接口从外部存储设备(如U盘)启动,通常用于更新固件或加载特定的镜像。

2. 命令行模式(Command Line Mode)

        U-Boot提供一个交互式的命令行界面(CLI),用户可以通过串口终端或者其他输入设备与U-Boot进行交互。在命令行模式下,用户可以执行各种命令,如:

  • 加载和启动镜像:使用bootmbootz命令加载内核镜像并启动。

  • 内存操作:如读写内存、检查内存等操作。

  • 存储操作:如读取、写入Flash存储器或SD卡中的数据。

  • 网络操作:通过ping测试网络连通性,使用tftp命令从网络服务器下载文件。

命令行模式主要用于开发、调试和测试阶段,提供了强大的灵活性和控制能力。

3. 自动引导模式(Autoboot Mode)

        U-Boot可以配置为在启动时自动执行一系列预定义的命令,这种自动引导模式通过环境变量(如bootcmd)来配置。常见的操作包括:

  • 自动加载内核镜像和设备树文件(Device Tree Blob,DTB)。
  • 设置内核启动参数。
  • 启动操作系统。

自动引导模式通常用于量产设备,以确保系统上电后能够自动引导到操作系统,减少用户干预。

4. 更新模式(Update Mode)

        在嵌入式系统中,固件更新是一个非常重要的功能。U-Boot提供了多种更新固件的方式:

  • U盘更新:通过USB设备(如U盘)加载新固件并更新到存储器中。

  • 网络更新:通过网络(如TFTP、HTTP)下载固件更新包并进行更新。

  • SD卡更新:通过SD卡加载新的固件版本进行更新。

更新模式通常会结合命令行模式或者自动引导模式,通过执行特定的脚本或命令实现。

5. 恢复模式(Recovery Mode)

恢复模式用于在系统引导失败或者固件损坏时,恢复系统。U-Boot可以通过某些硬件信号(如按键)或者特定的环境变量进入恢复模式:

  • 进入恢复模式后,U-Boot可能会进入一个特定的状态,允许用户通过串口终端或者其他输入设备进行故障排查和恢复操作。

  • 在恢复模式下,可以重新加载新的固件、修复文件系统或者进行其他的恢复操作。

6. 诊断模式(Diagnostic Mode)

        在某些情况下,U-Boot可以配置为进入诊断模式,用于检查硬件状态、调试问题等:

  • 通过串口输出硬件状态信息。

  • 测试硬件外设,如网络接口、存储设备等。

  • 诊断模式主要用于开发和测试阶段,有助于识别和解决硬件和软件问题。

7. 固件保护和安全启动模式(Secure Boot Mode)

U-Boot支持安全启动模式,通过签名验证加载的镜像,以确保固件的完整性和可信性:

  • 签名验证:在加载内核或者其他二进制文件之前,U-Boot会检查它们的数字签名,确保它们没有被篡改。

  • 加密引导:U-Boot还可以支持加密的固件镜像,防止未授权的访问。

  • 安全启动模式通常用于需要高安全性的嵌入式设备,如物联网设备、工业控制器等。

3. U-boot启动过程

        在嵌入式系统中,U-Boot是一个重要的引导程序,它的启动过程通常分为多个阶段。了解U-Boot的启动过程有助于更好地配置和调试系统。下面是U-Boot启动过程的详细步骤:

1. 上电复位(Power-on Reset)

        当嵌入式系统上电或者复位时,CPU通常会从一个固定的地址开始执行代码。这段地址通常位于ROM或Flash中,并且存储了最初始的引导代码(Boot ROM或者Bootloader的第一级)。

2. 板级引导代码(Board-Specific Boot Code)

        这个阶段的引导代码通常是片上系统(SoC)内置的最小引导程序,它的作用是设置基本的硬件状态,使系统进入可用状态。具体操作包括:

  • 初始化栈指针(Stack Pointer)。

  • 设置时钟频率和电源管理。

  • 初始化内存控制器,确保RAM可以正常访问。

  • 跳转到U-Boot的开始地址(通常是Flash存储器中的某个地址)。

3. U-Boot本身的启动

        U-Boot本身的启动可以分为多个阶段,分别是前引导阶段(Pre-boot)、板级初始化(Board Initialization)、硬件初始化(Hardware Initialization)、环境初始化(Environment Initialization)和引导操作系统(Boot Operating System)。

        3.1. 前引导阶段(Pre-boot Stage)

  • 入口点(Entry Point): U-Boot的入口点是编译时定义的一个固定地址。CPU从这个地址开始执行U-Boot代码。

  • 设置临时堆栈(Temporary Stack Setup): 在此阶段,U-Boot设置一个临时的堆栈空间,通常位于片内RAM中,以便进行后续的初始化操作。

        3.2. 板级初始化(Board Initialization)

  • 板级初始函数(Board Init F): U-Boot调用板级初始化函数board_init_f(),这个函数用于初始化系统所需的最基本的硬件资源,如时钟、串口和临时内存空间等。

  • 迁移到RAM(Relocation to RAM): U-Boot将自身从Flash或者ROM复制到RAM中,因为在RAM中执行程序速度更快,并且可以进行更多的操作。这个过程中,U-Boot重新定位了自身的代码和数据段。

        3.3. 硬件初始化(Hardware Initialization)

  • 板级初始化函数(Board Init R): U-Boot调用board_init_r()函数,完成更高级别的硬件初始化操作,包括:

    • 设置完整的内存控制器,确保整个系统的RAM可用。

    • 初始化控制台串口,允许用户与U-Boot进行交互。

    • 初始化必要的外设,如I2C、SPI、以太网等。

  • 设备树加载(Device Tree Blob Loading): 如果使用设备树,U-Boot会加载设备树Blob(DTB),为操作系统提供硬件配置信息。

        3.4. 环境初始化(Environment Initialization)

  • 加载环境变量(Environment Variables Loading): U-Boot加载存储在Flash、EEPROM或其他存储介质中的环境变量。这些环境变量通常包含引导命令、引导参数、网络配置等。

  • 命令行接口(Command Line Interface): 初始化命令行接口,允许用户通过串口或者其他接口输入命令,进行手动操作和调试。

        3.5. 引导操作系统(Boot Operating System)

  • 自动引导(Autoboot): U-Boot检查环境变量bootcmd,如果设置了自动引导命令,U-Boot会自动执行该命令,通常是加载内核镜像并启动操作系统。

  • 加载内核镜像(Kernel Image Loading): 根据引导命令,U-Boot加载内核镜像(如uImage、zImage)到RAM中,并准备必要的启动参数(如设备树文件、initrd等)。

  • 启动操作系统(Starting the Kernel): U-Boot将内核镜像传递给操作系统的入口点,并将控制权交给操作系统。至此,U-Boot的任务完成,系统进入操作系统阶段。

4. 操作系统启动

        当U-Boot将控制权转移给操作系统后,操作系统开始运行,并初始化自身的内核和用户空间服务。此时,U-Boot的任务已经完成,除非系统重新启动或者复位。

4. U-boot的SPL阶段和主程序阶段

       U-Boot的启动过程可以清晰地分为SPL(Secondary Program Loader)阶段主程序阶段(Main U-Boot Stage)

        在上述叙述中,上电复位、板级引导代码、前引导阶段、板级初始化可以归纳为SPL阶段,主要负载基础硬件初始化和加载U-boot主程序到RAM中

        硬件初始化、环境初始化、引导操作程序可以归纳为U-boot主程序阶段,主要继续的硬件初始化、环境初始化和最终的操作系统引导。

        在这里可以能会有一个问题为什么"u-boot在SPL阶段已经实现硬件初始化并将u-boot复制到RAM中,主阶段为什么还要进行硬件初始化在把u-boot复制到RAM"?

        答:这是一个常见的误解,实际上U-Boot启动过程中在SPL阶段和主阶段的硬件初始化以及内存复制(重定位)有着不同的目的和细节。

  • SPL阶段的初始化和复制:主要是基本的硬件初始化和将U-Boot主程序从存储介质加载到RAM中。
  • U-Boot主阶段的初始化和重定位:在此阶段,U-Boot执行更复杂的硬件初始化,启用更多的系统功能,并将自身重新定位到RAM中的合适位置。这是为了优化U-Boot的运行环境和内存使用,为引导操作系统做好准备。

        所以,虽然在SPL阶段已经进行了初步的硬件初始化和内存复制,但在U-Boot主阶段需要进行更全面的硬件初始化和重定位操作,以确保系统的最佳性能和正确的功能。

        用大白话叙述就是:RAM的访问速度比Flash快得多,而且RAM是读写都可以的,所以在RAM中运行主程序可以提高效率。SPL只是把为了U-boot主程序更好的、更快的运行,将U-boot主程序复制进RAM中运行,不是把U-boot复制进RAM中;真正的的核心由u-boot主任务在RAM中实现;

4. 内核配置、编译和移植

        Linux内核(英语:Linux Kernel)是一个开源、模块化的操作系统内核,是Linux操作系统的核心部分。它负责管理系统资源,为硬件和软件之间的交互提供接口,并提供操作系统的基本功能,如进程管理、内存管理、设备驱动、文件系统和网络堆栈等。Linux内核被广泛应用于从嵌入式系统到超级计算机的各种平台。

Linux 内核的主要作用包括以下几个方面:

1. 硬件抽象层(Hardware Abstraction Layer)

        Linux 内核充当硬件和软件之间的中介,提供一个硬件抽象层,使得应用程序可以在不需要了解底层硬件细节的情况下运行。通过硬件抽象,内核能够在不同的硬件平台上提供一致的接口和服务,保证了软件的可移植性和兼容性

2. 进程管理(Process Management)

        内核负责管理系统中的所有进程,包括进程的创建、调度、切换和终止等操作。内核通过调度程序(Scheduler)来分配 CPU 资源,确保系统中的多个进程能够高效地并行执行。进程管理功能还包括进程间通信(IPC)、进程优先级设置和资源分配等。

3. 内存管理(Memory Management)

        内核负责管理系统的内存,包括物理内存和虚拟内存。内存管理的任务包括内存分配与释放、内存映射、虚拟内存分页等。通过内存管理,内核可以为每个进程分配独立的虚拟地址空间,提供进程之间的隔离和保护机制。

4. 文件系统管理(File System Management)

        内核提供文件系统的支持,负责管理数据的存储和检索。它支持多种文件系统格式(如 ext4、FAT32、NTFS 等),并提供统一的接口供用户空间程序使用。内核的文件系统管理功能包括文件读写操作、文件权限管理、目录操作和文件系统挂载等。

5. 设备驱动管理(Device Driver Management)

        内核通过设备驱动程序(Device Drivers)与硬件设备进行交互。每种硬件设备(如硬盘、网络接口、图形卡等)都需要相应的设备驱动程序来处理设备的输入输出操作。内核提供了一个标准的设备驱动接口,使得开发者可以方便地为新设备编写驱动程序,并将其集成到系统中。

6. 网络协议栈(Networking Stack)

        内核实现了网络协议栈,支持各种网络协议(如 TCP/IP、UDP、ICMP 等)。网络协议栈负责处理网络通信的所有细节,包括数据包的发送和接收、路由选择、数据校验和流量控制等。内核的网络功能使得 Linux 系统能够作为网络服务器、路由器、防火墙等网络设备使用。

7. 安全与权限管理(Security and Permission Management)

        内核提供了安全和权限管理机制,确保系统的安全性和数据的完整性。它实现了用户身份验证、访问控制、SELinux 等安全机制,防止未授权访问和潜在的恶意操作。内核还提供了审计和日志记录功能,用于监控系统的安全事件。

8. 电源管理(Power Management)

        内核管理系统的电源状态,特别是在移动设备和嵌入式系统中,它通过电源管理功能控制设备的睡眠、唤醒和省电模式,以最大限度地节约电力。

        首先需要获得内核源码Linux 内核档案 (kernel.org)、配置交叉编译工具链;

1. 配置内核

        1. 选择开发板内核配置文件

  • 每个开发板或 SoC 通常都有一个默认的内核配置文件(如 defconfig 文件)。这些文件通常位于内核源码的 arch/<architecture>/configs/ 目录下。
  • 例如,如果你使用的是 100ask_imx6ull 开发板,那么可能会有一个名为 100ask_imx6ull_defconfig 的配置文件。

        2. 加载内核配置

make ARCH=arm 100ask_imx6ull_defconfig

        在这个例子中,ARCH=arm 指定了目标架构为 ARM,100ask_imx6ull_defconfig 是开发板的默认配置文件。 

2. 编译Linux内核

        1. 确保已经配置好交叉编译工具;

        2. 使用 make 命令编译内核及相关模块。

make zImage
make modules
  • zImage:压缩内核映像,适用于大多数嵌入式系统。
  • uImage:U-Boot 使用的内核映像格式,可以使用 mkimage 工具生成。

        3. 编译根文件系统(可选):

        如果需要,还可以编译根文件系统。可以使用 Buildroot、Yocto 或手动创建根文件系统。

3. 移植内核 

3.1 准备目标系统

        1. 创建目标文件系统:

        将编译好的内核映像设备树文件(DTB)根文件系统准备好,通常会将这些文件放在适当的存储介质中(如 SD 卡、NAND Flash)。

        2. 设备树文件(Device Tree Blob):

        设备树文件(.dtb)描述了硬件平台的详细信息,使内核能够识别和初始化硬件。使用 make dtbs 编译设备树文件。

        3.移植到目标板:

        将编译好的内核映像、设备树文件和根文件系统拷贝到目标板上的适当位置。可以通过各种方式进行传输,如 SD 卡、NAND Flash、网络等。

3.2 配置引导加载程序(Bootloader)

        如果使用 U-Boot 作为引导加载程序,需要配置 U-Boot 以加载和启动新的内核映像。配置 U-Boot 以加载内核、设备树文件和根文件系统。

4. 制作根文件系统

        使用 Buildroot 来制作嵌入式 Linux 系统的根文件系统是一种非常有效的方法。Buildroot 是一个简单、高效且可扩展的工具,可以用来生成嵌入式 Linux 系统所需的所有文件,包括内核、根文件系统、Bootloader 和用户空间应用程序。

        制作步骤:

1. 下载 Buildroot

        首先,你需要下载 Buildroot 的源码。你可以从 Buildroot 的官方网站或通过 Git 克隆它的源码:

git clone https://git.buildroot.org/buildroot
cd buildroot

2. 配置Buildroot

        需要指定目标硬件平台、工具链、软件包等。你可以使用 Buildroot 提供的 make menuconfig 命令来配置你的构建。

make menuconfig

在这个菜单中,你可以进行以下配置:

  • Target Options:选择目标架构(例如 ARM、x86 等)。
  • Toolchain:选择交叉编译工具链,Buildroot 提供了多种预编译的工具链选项。
  • System Configuration:设置目标系统的名称、版本等。
  • Kernel:选择是否编译 Linux 内核以及使用哪个内核版本。
  • Target Packages:选择要包括在根文件系统中的用户空间应用程序和库。
  • Filesystem Images:选择生成的根文件系统的格式(例如 ext4、cpio、squashfs 等)。

选择完配置后,保存并退出。

3. 使用现成的配置(可选)

        Buildroot 提供了很多预先定义的配置文件(defconfig),你可以使用这些配置文件来快速开始。这些配置文件通常位于 configs/ 目录下。

例如,使用 qemu_arm_vexpress_defconfig 作为默认配置:

make qemu_arm_vexpress_defconfig

 这会加载一个针对 ARM VExpress 板的默认配置。

4. 编译 Buildroot

        配置完成后,使用 make 命令开始编译。这将根据配置自动下载、编译和安装所需的所有软件包,并生成根文件系统。

make

 编译过程可能需要一些时间,具体取决于你的配置和系统性能。

5. 移植

        将生成的根文件系统镜像烧录到存储设备(如 SD 卡、eMMC 或 NAND)上,或者通过网络文件系统(NFS)进行加载。你需要确保开发板的引导加载程序(如 U-Boot)已正确配置为加载生成的内核和根文件系统。

        根文件系统有什么用?

        Linux 根文件系统(Root Filesystem)是 Linux 操作系统的核心部分之一,它在系统启动时提供了一个标准的目录结构和操作系统所需的基本文件

1. 提供操作系统的基本环境

        根文件系统包含了 Linux 操作系统启动和运行所需的所有基本文件和目录,包括系统配置文件、系统库、工具程序、设备文件等。它提供了一个标准化的环境,使得内核和用户程序能够正常工作。

2. 管理系统文件和目录

        根文件系统定义了 Linux 系统的目录结构,如 /bin/etc/lib/usr/home 等。这些目录分别用于存放系统命令、配置文件、共享库、用户程序和用户数据等。通过这种标准化的目录结构,Linux 系统能够有效管理系统文件和用户数据。

3. 支持系统的启动过程

        在系统启动过程中,根文件系统是操作系统的一个关键组成部分。当 Linux 内核被加载并初始化之后,它会挂载根文件系统,并执行根文件系统中的第一个用户空间进程(通常是 /sbin/init 或者系统管理器如 systemd),从而启动其他所有的系统服务和应用程序。

4. 提供运行时所需的库和工具

        根文件系统包含了操作系统运行所需的所有基础库和工具。例如,系统库(通常位于 /lib/usr/lib)提供了基本的系统调用接口;系统工具(如 /bin/sh/bin/ls 等)提供了基本的命令行工具和功能。这些组件共同确保了系统的正常运行。

5. 包含设备文件和挂载点

        根文件系统中的 /dev 目录包含了所有设备文件,这些文件代表了系统中的各种硬件设备(如硬盘、网络接口等)。这些设备文件通过 Linux 的虚拟文件系统(VFS)与实际设备进行交互。此外,根文件系统还包含挂载点(如 /mnt/media 等),用于挂载其他文件系统或设备。

6. 作为容器和嵌入式系统的基础

        在容器化技术(如 Docker)和嵌入式系统中,根文件系统通常是最小化的版本,以便减少存储空间和提高启动速度。它提供了运行特定应用程序或服务的最小环境,这对于嵌入式设备和容器化应用非常重要。

        

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值