当前位置: 首页 > news >正文

嵌入式 ARM Linux 系统构成(1):Bootloader层

目录

一、Bootloader 概述

1.1 核心作用

1.2 典型启动流程

二、ARM Bootloader 架构详解

2.1 多阶段启动设计

2.2 关键代码流程 

2.3. Bootloader的加载过程

2.4. Bootloader的加载方式

2.5. Bootloader 的移植

三、常见的Bootloader介绍

3.1.  U-Boot

3.2. vivi

3.3. Blob(BootLoader Object)

3.4. ARMboot

3.5. RedBoot

四、典型问题解决方案

4.1 启动卡死问题排查

4.2 环境变量修复

4.3 安全启动配置

五、性能优化技巧

5.1 启动时间优化

5.2 存储布局优化

六、 高级调试技术

6.1 异常跟踪方法

七、 常见问题 FAQ

八、总结

九、参考资料


嵌入式ARM Linux系统因其高效、低功耗的特点,在智能手机、家用电器、汽车控制系统等领域得到了广泛应用。作为系统启动的第一道门槛,Bootloader层在嵌入式Linux系统中扮演着至关重要的角色。

一、Bootloader 概述

1.1 核心作用

Bootloader 是嵌入式系统的"第一行代码",承担着从冷启动到操作系统加载的关键桥梁作用。其主要功能包括:

  • 硬件初始化:时钟、DDR、外设控制器

  • 介质检测:识别存储设备(NOR/NAND Flash, eMMC, SD卡)

  • 镜像加载:定位并加载内核及设备树

  • 协议支持:实现TFTP、USB、UART等传输协议

  • 安全启动:验签机制(可选)

1.2 典型启动流程

  1. ROM Code → 2. SPL → 3. TPL → 4. U-Boot → 5. Linux Kernel

二、ARM Bootloader 架构详解

2.1 多阶段启动设计

┌────────────┐   ┌───────────────┐   ┌───────────┐
│  Boot ROM  │ → │ Secondary PL  │ → │  U-Boot   │
└────────────┘   └───────────────┘   └───────────┘(固化在芯片)       (SPL/TPL)           (完整功能)

①SPL(Secondary Program Loader)

  • 特点体积 < 64KB,无动态内存

  • 功能

    • 初始化基础时钟

    • 配置DDR控制器

    • 加载TPL/U-Boot到RAM

② U-Boot 主体

  • 功能集:

    • 设备树解析

    • 文件系统支持(FAT, EXT4)

    • 网络协议栈(PING, TFTP)

    • 命令交互接口

2.2 关键代码流程 

// arch/arm/lib/crt0.S
_start:b   resetldr pc, _undefined_instruction/* ... 异常向量表 ... */reset:/* 关闭MMU/Cache */mrc p15, 0, r0, c1, c0, 0bic r0, r0, #0x00002000bic r0, r0, #0x00000007mcr p15, 0, r0, c1, c0, 0/* 设置栈指针 */ldr sp, =CONFIG_SYS_INIT_SP_ADDR/* 跳转到C入口 */bl  board_init_f

2.3. Bootloader的加载过程

Bootloader的启动过程通常分为两个阶段:Stage1和Stage2。

①Stage1(硬件初始化阶段)

  • 硬件初始化:此阶段,Bootloader会执行基本的硬件初始化,包括屏蔽中断、设置CPU速度和时钟频率、初始化RAM、初始化LED系统指示灯以及关闭CPU内部指令/数据cache等。这些初始化操作为后续阶段和操作系统的执行提供了必要的硬件环境。
  • 准备RAM空间:为了加载Stage2,Bootloader需要准备一段可用的RAM空间。通常涉及测试RAM的读写能力,以确保所选地址范围是有效的RAM空间。
  • 拷贝Stage2到RAM:将Stage2的可执行映像从固态存储设备(如ROM、EEPROM、FLASH等)拷贝到准备好的RAM空间中。
  • 设置堆栈指针:为执行C语言代码,需要设置堆栈指针。
  • 跳转到Stage2:完成以上步骤后,Bootloader会跳转到Stage2的C语言入口点开始执行。

②Stage2

  • 初始化硬件设备:在Stage2中,Bootloader会进一步初始化本阶段需要使用的硬件设备,如串口、计时器等。
  • 检测系统内存映射:内存映射是指在整个物理地址空间中,哪些地址范围被分配以用作寻址系统的RAM单元。Stage2会检测系统内存映射,以便正确加载和访问操作系统或应用程序。
  • 加载操作系统或应用程序:根据预定义的引导策略,Bootloader会从选定的引导设备(如闪存、外部存储器、串口等)中读取操作系统镜像或应用程序,并将其加载到内存中。
  • 设置启动参数:为操作系统或应用程序设置必要的启动参数,如内核命令行参数等。
  • 启动操作系统或应用程序:一旦操作系统或应用程序加载到内存中并设置好启动参数,Bootloader会跳转到该程序的入口点,启动执行。对于操作系统,这意味着将控制权移交给操作系统内核;对于应用程序,则开始执行应用程序的主函数。

2.4. Bootloader的加载方式

Bootloader的加载方式取决于具体的硬件平台和引导需求。常见的加载方式包括:

  • 从Flash存储器加载:如果Bootloader已经烧录到Flash存储器中,系统上电后会自动从Flash加载Bootloader到内存并启动。
  • 通过UART接口加载:可以通过UART接口使用特定的命令(如loadb)将Bootloader加载到内存中。这种方式通常用于调试和更新Bootloader。
  • 通过网络加载:如TFTP(Trivial File Transfer Protocol)等网络协议,可以将Bootloader从主机下载到目标机的内存中。这种方式适用于远程调试和升级。
  • 从SD卡加载:可以将Bootloader写入SD卡,然后通过SD卡启动系统。这种方式常用于嵌入式系统的固件升级和恢复。 

2.5. Bootloader 的移植

①移植步骤

  • 硬件相关代码修改:首先需要根据目标硬件平台,修改 Bootloader 中与硬件初始化相关的代码。包括修改时钟配置、内存控制器配置、串口等设备驱动代码。例如,对于新的 ARM 芯片,可能需要重新计算 PLL 的分频系数,以获得合适的时钟频率。
  • 设备树修改:如果目标硬件平台使用设备树,需要根据实际硬件情况修改设备树文件。添加或修改硬件设备节点,确保设备树能够准确描述硬件设备的信息。例如,添加新的 GPIO 控制器节点,并配置其相关属性。
  • 编译和下载:完成代码修改后,使用交叉编译工具链对 Bootloader 进行编译,生成可执行文件。然后通过 JTAG、串口等方式将 Bootloader 下载到目标硬件平台上进行测试和调试。

②注意事项

  • 在移植过程中,仔细阅读目标硬件平台的参考手册,确保对硬件的理解准确无误。例如,对于内存控制器的配置,不同的芯片可能有不同的寄存器设置方式。
  • 注意 Bootloader 与内核之间的兼容性。一些内核版本可能对 Bootloader 传递的启动参数有特定要求,需要根据内核版本进行相应的调整。
  • 调试移植过程中的问题时,可以充分利用串口输出的调试信息。通过在关键代码位置添加打印语句,逐步排查问题。

三、常见的Bootloader介绍

在嵌入式ARM Linux系统中,常见的Bootloader包括U-Boot、vivi、Blob等。

3.1.  U-Boot

U-Boot是一种广泛应用于嵌入式ARM系统的开源Bootloader。U-Boot是遵循GPL条款的开放源码项目,支持多种处理器架构如PowerPC、ARM、X86、MIPS等,能够适配上百种开发板。提供了丰富的外设驱动支持,支持多个文件系统,并附带调试、脚本、引导等工具。U-Boot特别支持Linux系统,为板级移植做了大量工作,是功能最多、灵活性最强且开发最积极的开源Bootloader之一。

  • 功能特点
    • 支持从多种存储设备中加载内核镜像,如Flash存储器、硬盘等。
    • 可以通过网络进行远程启动,方便进行远程系统升级和设备部署。
    • 提供了丰富的配置选项和命令行接口,方便开发者进行调试和定制。
  • 应用场景:在工业物联网设备的批量生产中,U-Boot可以方便地对大量设备进行内核更新和配置。同时,它也广泛应用于智能手机、平板电脑等高性能嵌入式设备中。

3.2. vivi

  • 特点:vivi是由韩国Mizi公司开发的一种Bootloader,专门针对ARM9处理器而设计,支持S3C2410x处理器。提供了两种工作模式:启动加载模式和下载模式。在下载模式下,vivi为用户提供一个命令行接口,方便用户进行调试和烧写操作。
  • 应用:vivi主要应用于基于ARM9处理器的嵌入式系统中。

3.3. Blob(BootLoader Object)

  • 特点:Blob是由Jan-Derk Bakker和Erik Mouw发布的Bootloader,专为StrongARM构架下的LART设计。它支持SA1100的LART主板,但用户也可以自行修改移植。Blob提供了两种工作模式,并具备较齐全的功能和较少的代码量,适合进行修改移植来引导Linux系统。
  • 应用:Blob主要应用于基于StrongARM构架的嵌入式系统中,如S3C44B0板等。

3.4. ARMboot

  • 特点:ARMboot是一个ARM平台的开源固件项目,它严重依赖于PPCBoot。ARMboot支持的处理器构架有StrongARM、ARM720T、PXA250等,是为基于ARM或StrongARM CPU的嵌入式系统所设计的。ARMboot的目标是成为通用的、容易使用和移植的引导程序,非常轻便地运用于新的平台上。
  • 应用:ARMboot应用于基于ARM或StrongARM处理器的嵌入式系统中,提供了一个轻便且功能完备的引导解决方案。

3.5. RedBoot

  • 特点:RedBoot是标准的嵌入式调试和引导解决方案,是一个专门为嵌入式系统定制的引导工具。它最初由Redhat开发,是嵌入式操作系统eCos的一个最小版本,并随eCos发布。RedBoot支持串口、网络下载和执行嵌入式应用程序,既可以用在产品的开发阶段(调试功能),也可以用在最终的产品上(Flash更新、网络启动)。
  • 应用:RedBoot广泛应用于各种嵌入式系统中,特别适用于需要远程调试、升级和配置的场景。

四、典型问题解决方案

4.1 启动卡死问题排查

①串口日志分析

U-Boot 2023.07 (Oct 10 2023 - 14:20:00 +0800)CPU: i.MX6ULL rev1.2 792 MHz (running at 396 MHz)
Reset cause: POR
Model: Freescale i.MX6 ULL 14x14 EVK Board
DRAM:  512 MiB
MMC:  FSL_SDHC: 0, FSL_SDHC: 1
*** Warning - bad CRC, using default environment

常见错误标识:CRC错误、时钟配置警告

②JTAG 调试流程

  • 设置断点:board_init_f()

  • 寄存器检查:

    • CP15 控制寄存器

    • DDRCTL 配置寄存器

  • 内存测试: 

=> md 0x80000000 100
=> mw 0x80000000 0xdeadbeef

4.2 环境变量修复

# 重置默认环境
env default -a
saveenv# 手动设置启动参数
setenv bootcmd 'mmc dev 0; ext4load mmc 0:1 0x80800000 zImage; bootz 0x80800000 - 0x83000000'
setenv bootargs console=ttymxc0,115200 root=/dev/mmcblk0p2 rootwait
saveenv

4.3 安全启动配置

U-Boot 签名验证示例:

# 生成密钥
openssl genrsa -out key.pem 2048# 签名镜像
tools/mkimage -F -k keydir/ -K u-boot.dtb -r -o signed -K key.pem u-boot.bin# 验证配置
CONFIG_FIT_SIGNATURE=y
CONFIG_RSA_VERIFY=y

五、性能优化技巧

5.1 启动时间优化

①精简功能:

# configs/imx6ull_defconfig
-CONFIG_CMD_NET=y
-CONFIG_USB=y
+CONFIG_BOOTDELAY=0

②时钟优化策略:

  • 提前提升CPU主频

  • 使用SPL跳过重复初始化

③并行初始化:

// 启用DMA初始化存储设备
mmc_init_stream(dev);

5.2 存储布局优化

典型分区方案:

Device     Boot  Start     End Sectors  Size Id Type
/dev/mmcblk0p1  2048   34815   32768   16M  a U-Boot
/dev/mmcblk0p2 34816  262143  227328  111M 83 Linux
/dev/mmcblk0p3 262144 1048575 786432  384M 83 Linux

六、 高级调试技术

6.1 异常跟踪方法

①未定义指令处理:

void show_regs(struct pt_regs *regs)
{printf("PC : [<%08lx>] LR : [<%08lx>]\n",regs->ARM_pc, regs->ARM_lr);/* 打印完整寄存器上下文 */
}

②内存保护调试:

=> cp.b 0x80000000 0x81000000 0x100000
=> cmp.b 0x80000000 0x81000000 0x100000

七、 常见问题 FAQ

Q1: 如何判断DDR初始化是否成功?
A: 使用内存测试命令,或观察串口输出的DRAM容量信息

Q2: U-Boot无法保存环境变量怎么办?
A: 检查存储设备分区,确认环境变量区偏移量设置正确

Q3: 启动卡在"Starting kernel..."可能原因?
A: 设备树地址错误、内核镜像损坏或启动参数不匹配

Q4: 如何实现双系统启动?
A: 通过bootcmd脚本实现条件分支:

if mmc dev 1; then run boot_linux; else run boot_rtos; fi

八、总结

Bootloader层在嵌入式ARM Linux系统中扮演着至关重要的角色。它负责初始化系统硬件、加载操作系统,并将控制权转移到操作系统的启动过程。了解Bootloader的功能、作用、加载过程以及常见问题对于嵌入式系统开发者来说至关重要。


九、参考资料

  • 《U-Boot Porting Guide》

  • 《ARM Architecture Reference Manual》

  • ARM架构的BootLoader详解——对于Linux与Baremetal(裸机MCU)_arm bootloader-CSDN博客


相关文章:

嵌入式 ARM Linux 系统构成(1):Bootloader层

目录 一、Bootloader 概述 1.1 核心作用 1.2 典型启动流程 二、ARM Bootloader 架构详解 2.1 多阶段启动设计 2.2 关键代码流程 2.3. Bootloader的加载过程 2.4. Bootloader的加载方式 2.5. Bootloader 的移植 三、常见的Bootloader介绍 3.1. U-Boot 3.2. vivi …...

ArcGIS Pro 基于基站数据生成基站扇区地图

在当今数字化的时代&#xff0c;地理信息系统&#xff08;GIS&#xff09;在各个领域都发挥着至关重要的作用。 ArcGIS Pro作为一款功能强大的GIS软件&#xff0c;为用户提供了丰富的工具和功能&#xff0c;使得数据处理、地图制作和空间分析变得更加高效和便捷。 本文将为您…...

GaussianCity:实时生成城市级数字孪生基底的技术突破

在空间智能领域,如何高效、大规模地生成高质量的3D城市模型一直是一个重大挑战。传统方法如NeRF和3D高斯溅射技术(3D-GS)在效率和规模上存在显著瓶颈。GaussianCity通过创新性的技术方案,成功突破了这些限制,为城市级数字孪生的构建提供了全新路径。 一、核心创新:突破传…...

【个人学习总结】反悔贪心:反悔堆+反悔自动机

参考&#xff1a;【学习笔记】反悔贪心 - RioTian 什么是反悔贪心&#xff1f; 反悔贪心&#xff0c;就是可以回溯的贪心&#xff0c;一般题目我们能使用正常贪心的情况是很少的&#xff0c;因为我们只考虑了局部最优解&#xff0c;我们不能保证局部最优解是最后的最优解&…...

通往 AI 之路:Python 机器学习入门-线性代数

2.1 线性代数&#xff08;机器学习的核心&#xff09; 线性代数是机器学习的基础之一&#xff0c;许多核心算法都依赖矩阵运算。本章将介绍线性代数中的基本概念&#xff0c;包括标量、向量、矩阵、矩阵运算、特征值与特征向量&#xff0c;以及奇异值分解&#xff08;SVD&…...

迷你世界脚本UI五子棋小游戏

wzq_jm "7477124677881080183-22855"--界面id wzq_jmjxh "7477124677881080183-22855_"--界面加下划线 wzq_tc "7477124677881080183-22855_262"--退出按钮id wzq_hdlt1 "7477124677881080183-22855_267"--互动聊天按钮 快点吧&a…...

阿里万相,正式开源

大家好&#xff0c;我是小悟。 阿里万相正式开源啦。这就像是AI界突然开启了一扇通往宝藏的大门&#xff0c;而且还是免费向所有人敞开的那种。 你想想看&#xff0c;在这个科技飞速发展的时代&#xff0c;AI就像是拥有神奇魔法的魔法师&#xff0c;不断地给我们带来各种意想…...

C# 数据转换

1. 文本框读取byte&#xff0c;ushort格式数据 byte addr; if (byte.TryParse(textBoxAddr.Text, out addr) true) {}2. 字节数组 (byte[]) 转换为 ASCII 字符串 byte[] bytes { 72, 101, 108, 108, 111 }; // "Hello" 的 ASCII 码 string s0 Encoding.ASCII.Ge…...

学习第十一天-树

一、树的基础概念 1. 定义 树是一种非线性数据结构&#xff0c;由 n 个有限节点组成层次关系集合。特点&#xff1a; 有且仅有一个根节点其余节点分为若干互不相交的子树节点间通过父子关系连接 2. 关键术语 术语定义节点包含数据和子节点引用的单元根节点树的起始节点&#…...

网络服务之SSH协议

一.SSH基础 1.1 什么是ssh SSH&#xff08;Secure Shell&#xff09;协议是一种用于字符界面远程登录和数据加密传输的协议。 1.2 ssh优点 优点&#xff1a; 数据传输是加密的&#xff0c;可以防止信息泄漏 数据传输是压缩的&#xff0c;可以提高传输速度 注意&#xff…...

蓝桥杯 之 前缀和与查分

文章目录 题目求和棋盘挖矿 前缀和有利于快速求解 区间的和、异或值 、乘积等情况差分是前缀和的反操作 前缀和 一维前缀和&#xff1a; # 原始的数组num,下标从1到n n len(num) pre [0]*(n1) for i in range(n):pre[i1] pre[i] num[i] # 如果需要求解num[l] 到num[r] 的区…...

GB28181开发--ZLMediaKit‌+WVP+Jessibuca‌

一、核心组件功能 1‌、ZLMediaKit‌ 定位‌:基于 C++11 的高性能流媒体服务框架,支持 RTSP/RTMP/HLS/HTTP-FLV 等协议互转,具备低延迟(最低 100ms)、高并发(单机 10W 级连接)特性,适用于商用级流媒体服务器部署‌。 ‌特性‌:跨平台(Linux/Windows/ARM 等)、支持 …...

Ubuntu20.04 在离线机器上安装 NVIDIA Container Toolkit

步骤 1.下载4个安装包 Index of /nvidia-docker/libnvidia-container/stable/ nvidia-container-toolkit-base_1.13.5-1_amd64.deb libnvidia-container1_1.13.5-1_amd64.deb libnvidia-container-tools_1.13.5-1_amd64.deb nvidia-container-toolkit_1.13.5-1_amd64.deb 步…...

如何快速上手RabbitMQ 笔记250304

如何快速上手RabbitMQ 要快速上手 RabbitMQ&#xff0c;可以按照以下步骤进行&#xff0c;从安装到基本使用逐步掌握核心概念和操作&#xff1a; 1. 理解核心概念 Producer&#xff08;生产者&#xff09;&#xff1a;发送消息的程序。Consumer&#xff08;消费者&#xff09…...

无人机端部署 AI 模型,实现实时数据处理和决策

在无人机端部署 AI 模型&#xff0c;实现实时数据处理和决策&#xff0c;是提升无人机智能化水平的关键技术之一。通过将 AI 模型部署到无人机上&#xff0c;可以实现实时目标检测、路径规划、避障等功能。以下是实现这一目标的详细方案和代码示例。 一、实现方案 1. 硬件选择…...

CentOS 7中安装Dify

Dify 是一个开源的 LLM 应用开发平台。其直观的界面结合了 AI 工作流、RAG 管道、Agent、模型管理、可观测性功能等&#xff0c;让您可以快速从原型到生产。尤其是我们本地部署DeepSeek等大模型时&#xff0c;会需要用到Dify来帮我们快捷的开发和应用。 大家可以参考学习它的中…...

CoDrivingLLM

CoDrivingLLM 思路 1.输入和输出 输入 算法的输入包括车辆当前时刻的状态 S t S_t St​ &#xff0c;这个状态包含了车辆的位置、速度、行驶方向等信息&#xff1b;以及参与协同驾驶的联网自动驾驶汽车列表C&#xff0c;用于确定需要进行决策的车辆集合。 输出 输出为车辆…...

Centos7升级openssl和openssh最新版

1、事前准备 下载openssl3.4.1和openssh9.9p2压缩包上传到服务器 https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable// Release OpenSSL 3.4.1 openssl/openssl GitHub 2、查看centos7、ssh以及openssl的版本信息 # 查看CentOS系统版本信息 cat /etc/redhat-release …...

相控阵扫盲

下图展示天线增益 在仰角为0度的情况下随着方位角的变化而变化。需要注意到的是在天线视轴方向上的高增益主瓣上还有几个低增益旁瓣 阵列因子乘以新的阵元方向图会形成指向性更强的波速...

nginx 配置 301跳转

HTTP 跳转到 HTTPS 将所有 HTTP 请求&#xff08;80 端口&#xff09;跳转到 HTTPS&#xff08;443 端口&#xff09;&#xff1a; server {listen 80;server_name example.com;# 跳转到 HTTPSreturn 301 https://$host$request_uri; }server {listen 443 ssl;server_name exa…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

Unit 1 深度强化学习简介

Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库&#xff0c;例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体&#xff0c;比如 SnowballFight、Huggy the Do…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...