【STM32-MAP文件分析】

STM32-MAP文件分析

  • ■ MDK编译生成文件简介
    • ■ .o
    • ■ .axf
    • ■ .hex
    • ■ .crf
    • ■ .d
    • ■ .dep
    • ■ .lnp
    • ■ .lst
    • ■ .map
    • ■ .build_log.htm
    • ■ .htm 文件
    • ■ .map 文件
  • ■ map文件分析
    • ■ map 文件的 MDK 设置
      • ■ 1. 要生成 map 文件 在 Listing 选项卡里面
      • ■ 2. Keil5 中打开.map 文件
    • ■ map 文件的基础概念
      • ■ 1. Section:程序段
      • ■ 2. RO: Read Only 的缩写,
      • ■ 3. RW: Read Write 的缩写,
      • ■ 4. ZI: Zero initialized 的缩写,
      • ■ 5. .text:相当于 RO code
      • ■ 6. .constdata:相当于 RO data
      • ■ 7. .bss:相当于 ZI data
      • ■ 8. .data:相当于 RW data
    • ■ map 文件的组成部分说明
      • ■ 1. 程序段交叉引用关系(Section Cross References)
      • ■ 2. 删除映像未使用的程序段(Removing Unused input sectionsfrom the image)
      • ■ 3. 映像符号表(Image Symbol Table)
        • ■ 3.1 本地符号(Local Symbols) 地址和大小
        • ■ 3.2 全局符号( Global Symbols)地址和大小
      • ■ 4. 映像内存分布图( Memory Map of the image)
      • ■ 5. 映像组件大小(Image component sizes)

■ MDK编译生成文件简介

MDK 编译工程,会生成一些中间文件(如 .axf、 .crf、 .d、 .dep、.hex、 .lnp、 .lst、 .o、 .htm、 bulild_log.htm 和.map等),最终生成 hex 文件,编译过程产生的所有文件,都存放在 Output 文件夹下
在这里插入图片描述

■ .o

可重定向 1对象文件,每个源文件(.c/.s 等)编译都会生成一个.o 文件
它是由编译器编译.c/.s 文件时所产生的可重定向对象文件,其文件名同.c/.s 文件一模一样,只是后缀为.o。所以,我们看到.o 就应该想到与之对应的.c 或者.s 文件,我们在分散加载里面经常会用到.o 文件。

■ .axf

由 ARMCC 编译生产的可执行对象文件,不可重定向 2(绝对地址)
多个.o 文件链接生成.axf 文件,我们在仿真的时候,需要用到该文件,
由 armlink 链接器,将整个工程参与编译的.o 文件链接成一个可执行对象文件,它是不可重定向的。有了该文件,我们就可以用仿真器来下载到 MCU 进行仿真调试了。
注意:各类仿真器,在进行下载调试的时候,都是使用的.axf 文件。

■ .hex

Intel Hex 格式文件,可用于下载到 MCU, .hex 文件和.bin 文件由.axf 文件转换而来可执行的对象文件
.hex 文件和.bin 文件的区别是: .bin 文件不含地址信息,全部都是可执行代码;而.hex 文件则是包含地址信息的可自行代码。
我们在使用 ISP 软件进行程序下载的时候,
一般使用的是.hex 文件,由 ISP 软件解析.hex 文件包含的地址信息来实现程序下载。而我们在进行 BootLoader 升级的时候,一般使用.bin 文件,地址由 Bootloader 程序指定。

■ .crf

交叉引用文件,包含浏览信息(定义、标识符、引用)

■ .d

由 ARMCC/GCC 编译生产的依赖文件(.o 文件所对应的依赖文件)
每个.o 文件,都有一个对应的.d 文件

■ .dep

整个工程的依赖文件

■ .lnp

MDK 生成的链接输入文件,用于命令输入

■ .lst

C 语言或汇编编译器生成的列表文件

■ .map

连接器生成的列表文件/MAP 文件, 该文件对我们非常有用!

■ .build_log.htm

最近一次编译工程时的日志记录文件

■ .htm 文件

链接生成的列表文件
它是编译器在编译代码的时候生成的一个列表文件, 包含了整个工程的静态调用图, 最大的用处就是可以查看栈深度(最小深度),方便设置栈大小。
它是编译器在编译代码的时候生成的一个列表文件, 包含了整个工程的静态调用图, 最大的用处就是可以查看栈深度(最小深度),方便设置栈大小。 .htm 文件可以直接由浏览器打开(双击打开)。 .htm 文件包含两部分内容:
1, 整个工程最大栈(Stack) 深度及其调用关系
我们打开:新建工程例程→Output→atk_h750.htm 文件(双击,注意:必须整个工程编译一遍,才会生成 atk_h750.htm 文件,否则是找不到这个文件的!),可以看到如图 1.2 所示:
在这里插入图片描述
可以看到,例程的最大栈深度是 416 字节,最大栈深时的调用关系为: __rt_entry_main⇒ main ⇒ sys_stm32_clock_init ⇒AL_RCC_ClockConfig ⇒ HAL_InitTick ⇒HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority。

不过需要注意的是,这里的最大栈深度仅仅是最低要求(静态栈),因为它并没有统计无栈深的函数(用内存管理)、递归函数、以及无法追踪的函数(函数指针)等所包含的栈(Stack)。
不过它给我们指明了最低需求,我们在分配栈深度的时候,就可以参考这个值来做设置,一般不低于静态栈的2倍。我们例程默认设置的栈深(Stack_Size)为0X800(通过.s文件设置),

2, 各个函数的栈深及其调用关系
.htm 文件还给出了每个函数所使用的栈深度以及其调用关系,如图 1.3 所示:
在这里插入图片描述
上图给出了 sys_stm32_clock_init 函数的最大栈深度及其调用关系,并且列出了其所调用的函数及其所被调用的函数。

■ .map 文件

对我们编程非常有帮助,是本文档重点要给大家介绍的,因此另起一节,进行重点说明。
其他文件类型及说明,请大家参考: MDK→help→uVision Help→B. File Types,如图 1.3所示:
在这里插入图片描述

■ map文件分析

map 文件是编译器链接时生成的一个文件,它主要包含了交叉链接信息。通过.map 文件,我们可以知道整个工程的函数调用关系、 FLASH 和 RAM 占用情况及其详细汇总信息,能具体到单个源文件(.c/.s)的占用情况,根据这些信息,我们可以对代码进行优化。

.map 文件可以分为以下 5 个组成部分:
1, 程序段交叉引用关系(Section Cross References)
2, 删除映像未使用的程序段(Removing Unused input sections from the image)
3, 映像符号表(Image Symbol Table)
4, 映像内存分布图(Memory Map of the image)
5, 映像组件大小(Image component sizes)

接下来,我们将分三个部分对 map 文件进行详细介绍:
1, map 文件的 MDK 设置
2, map 文件的基础概念
3, map 文件的组成部分说明

■ map 文件的 MDK 设置

■ 1. 要生成 map 文件 在 Listing 选项卡里面

要生成 map 文件,我们需要在 MDK 的魔术棒→Listing 选项卡里面,进行相关设置,如图 2.1.1 所示:
在这里插入图片描述
中红框框出的部分就是我们需要设置的,默认情况下, MDK 这部分设置就是全勾选的,如果我们想取消掉一些信息的输出,则取消相关勾选即可(一般不建议)。

■ 2. Keil5 中打开.map 文件

双击工程目标 LED(不同工程名字可能不一样),打开.map 文件。
在这里插入图片描述

■ map 文件的基础概念

为了更好的分析 map 文件,我们先对需要用到的一些基础概念进行一个简单介绍,相关概念如下:

■ 1. Section:程序段

描述映像文件的代码或数据块,我们简称程序段

■ 2. RO: Read Only 的缩写,

包括只读数据(RO data)和代码(RO code)两部分内容,占用 FLASH 空间

■ 3. RW: Read Write 的缩写,

包含可读写数据(RW data,有初值,且不为 0),占用 FLASH(存储初值)和 RAM(读写操作)

■ 4. ZI: Zero initialized 的缩写,

包含初始化为 0 的数据(ZI data),占用 RAM 空间。

■ 5. .text:相当于 RO code

■ 6. .constdata:相当于 RO data

■ 7. .bss:相当于 ZI data

■ 8. .data:相当于 RW data

■ map 文件的组成部分说明

■ 1. 程序段交叉引用关系(Section Cross References)

这部分内容描述了各个文件(.c/.s 等)之间函数(程序段)的调用关系,在这里插入图片描述
main.o(i.main) refers to sys.o(i.sys_stm32_clock_init) for sys_stm32_clock_init, 表示:
main.c文件中的main函数,调用了sys.c中的sys_stm32_clock_init函数。
其中:
i.main 表示 main 函数的入口地址
i.sys_stm32_clock_init 表示sys_stm32_clock_init 的入口地址。

■ 2. 删除映像未使用的程序段(Removing Unused input sectionsfrom the image)

这部分内容描述了工程中由于未被调用而被删除的冗余程序段(函数/数据),
在这里插入图片描述
例如 main.c 中没有调用到的rev16_text 等文件将被移除。

另外,在最后还有一个统计信息: 361 unused section(s) (total 43234 bytes) removed fromthe image. 表示总共移除了 361 个程序段(函数/数据),大小为 43234 字节。即给我们的MCU 节省了 43234 字节的程序空间。

为了更好的节省空间,我们一般在 MDK→魔术棒→C/C++选项卡里面勾选: One ELFSection per Function,如图 2.1.2.2 所示:
在这里插入图片描述

■ 3. 映像符号表(Image Symbol Table)

映像符号表(Image Symbol Table)描述了被引用的各个符号(程序段/数据)在存储器中的存储地址、类型、 大小等信息。
映像符号表分为两类:本地符号(Local Symbols)和全局符号(Global Symbols)。

■ 3.1 本地符号(Local Symbols) 地址和大小

记录了用 static 声明的全局变量地址和大小, c 文件中函数的地址和 用 static 声明的函数代码大小,汇编文件中的标号地址(作用域: 限本文件)
在这里插入图片描述
图中红框框处部分,表示 sys.c 文件中的 sys_stm32_clock_init 函数的入口地址为:0x08002bc8,类型为: Section(程序段),大小为 0。因为: i. sys_stm32_clock_init 仅仅表示 sys_stm32_clock_init 函数入口地址,并不是指令,所以没有大小。
在全局符号段,会列出sys_stm32_clock_init 函数的大小。
在这里插入图片描述

■ 3.2 全局符号( Global Symbols)地址和大小

全局符号(Global Symbols) 记录了全局变量的地址和大小, C 文件中函数的地址及其代码大小,汇编文件中的标号地址(作用域: 全工程), 全局符号如图 2.1.3.2.1 所示:
在这里插入图片描述
图中红框框处部分
表示 sys.c 文件中的 sys_stm32_clock_init 函数的入口地址为:0x08002bc9,类型为: Thumb Code(程序段),大小为 344 字节。
在这里插入图片描述

注意,此处Local Symbols: 的地址用的 0x080003e8,和Global Symbols: 0x080003e9地址不符,这是因为ARM 规定 Thumb 指令集的所有指令,其最低位必须为 1, 0x080003e9= 0x080003e8+ 1,所以才会有 2 个不同的地址,且总是差 1,实际上就是同一个函数。

Local Symbols:
在这里插入图片描述
Global Symbols:
在这里插入图片描述

■ 4. 映像内存分布图( Memory Map of the image)

映像文件分为加载域( Load Region)和运行域( Execution Region)
一个程序可以有多个加载域, 一个加载域必须有至少一个运行域(可以有多个运行域)。
加载域为映像程序的实际存储区域,而运行域则是 MCU 上电后的运行状态。加载域和运行域的简化关系(这里仅表示一个加载域的情况)
在这里插入图片描述
由图可知, RW 区也是存放在 ROM(FLASH)里面的,在执行 main 函数之前, RW(有初值且不为 0 的变量)数据会被拷贝到 RAM 区,同时还会在 RAM 里面创建 ZI 区(初始化为 0 的变量)。
在这里插入图片描述

序号描述
① 处表示映像的入口地址,也就是整个程序运行的起始地址,为: 0X0800 0299。 实际地址为: 0X0800 0298(Thumb 指令最低位是 1)。
② 处表示 LR_m_stmflash 加载域, 其起始地址为: 0X0800 0000;占用大小为: 0X0000 2D8C; 最大地址范围为: 0X0002 0000。
其内部包含两个运行域: ER_m_stmflash和 RW_m_stmsram。
③ 处表示 ER_m_stmflash 运行域,其起始地址为: 0X0800 0000;占用大小为: 0X0000 2D6C;最大地址范围为: 0X0002 0000;即 内部 FLASH 运行域,所有需要放内部 FLASH 的代码,都应该放到这个运行域里面。
对于 STM32F1/F4/F767 等开发板, 我们例程所有的代码,都是放在这个运行域的(名字可能不一样)。
④ 处表示 RW_m_stmsram 运行域,其起始地址为:0X2400 0000;占用大小为: 0X0000 2D6C;最大地址范围为: 0X0008 0000;即内部 SRAM 运行域,所有 RAM(包括 RW 和 ZI)都是放在这个运行域里面。
⑤ 处表示 LR_m_qspiflash 加载域,其起始地址为: 0X9000 0000;占用大小为: 0X0000 0720;最大地址范围为: 0X0080 0000。
其内部包含一个运行域: ER_m_qspiflash。
⑥ 处表示 ER_m_qspiflash 运行域,其起始地址为: 0X9000 0000;占用大小为: 0X0000 0720;最大地址范围为: 0X0080 0000;即外部 QSPI FLASH 运行域,所有需要放 外部 QSPI FLASH 的代码,都应该放到这个运行域里面。

如 sys_stm32_clock_init 函数:该函数在 ER_m_stmflash 运行域;入口地址为: 0X0800 2BC8;大小为: 0X168 字节;是 sys.c里面的函数。了解这些信息,对我们分析及优化程序非常有用。

■ 5. 映像组件大小(Image component sizes)

映像组件大小(Image component sizes)给出了整个映像所有代码(.o)占用空间的汇总信息,对我们比较有用,

在这里插入图片描述

在这里插入图片描述

① 处,表示.c/.s 文件生成对象所占空间大小(单位:字节,下同),即.c/.s 文件编译后所占代码空间的大小。
每个项所代表的意义如下:

类型作用
Code(inc.data):表示包含内联数据(inc.data)后的代码大小。
如 delay.o(即delay.c)所占的 Code 大小为 142 字节,其中 8 字节是内联数据。
RO Data:表示只读数据所占的空间大小,一般是指 const 修饰的数据大小。
RW Data:表示有初值(且非 0)的可读写数据所占的空间大小,它同时占用 FLASH和 RAM 空间。
ZI Data:表示初始化为 0 的可读写数据所占空间大小,它只占用 RAM 空间。
Debug:表示调试数据所占的空间大小,如调试输入节及符号和字符串。
Object Totals:表示以上部分链接到一起后,所占映像空间的大小。

(incl.Generated):表示链接器生产的映像内容大小,它包含在 Object Totals 里面了,这里仅仅是单独列出,我们一般不需要关心。
(incl.Padding) :表示链接器根据需要插入填充以保证字节对齐的数据所占空间的大小,它也包含在 Object Totals 里面了,这里单独列出,一般无需关心。

② 处,表示被提取的库成员( .lib)添加到映像中的部分所占空间大小。
各项意义同①中的说明。我们一般只用看 Library Totals 来分析库所占空间的大小即可。

③ 处,表示本工程全部程序汇总后的占用情况。其中:

类型作用
Grand Totals:表示整个映像所占空间大小。
ELF Image Totals:表示 ELF 可执行链接格式映像文件的大小,一般和 Grand Totals一样大小。
ROM Totals:表示整个映像所需要的 ROM 空间大小,不含 ZI 和 Debug 数据。
Total RO Size:表示 Code 和 RO 数据所占空间大小,本例程为: 13452 字节。
Total RW Size:表示 RW 和 ZI 数据所占空间大小,即本映像所需 SRAM 空间的大小,本例程为: 3032 字节。
Total ROM Size:表示 Code、 RO 和 RW 数据所占空间大小,即本映像所需 FLASH空间的大小,本例程为: 13484 字节。

打开debug后的Image component sizes
在这里插入图片描述

在这里插入图片描述
关闭debug后的Image component sizes
在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/862678.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信息学奥赛初赛天天练-38-CSP-J2021阅读程序-约数个数、约数和、埃氏筛法、欧拉筛法筛素数应用

PDF文档公众号回复关键字:20240628 2021 CSP-J 阅读程序3 1阅读程序(判断题1.5分 选择题3分 共计40分 ) 01 #include<stdio.h> 02 using namespace std; 03 04 #define n 100000 05 #define N n1 06 07 int m; 08 int a[N],b[N],c[N],d[N]; 09 int f[N],g[N]; 10 11 …

矩阵快速幂

矩阵快速幂 矩阵&#xff1a; 一个矩阵 A A A&#xff0c;是由 n m n\times m nm 个数字组成&#xff0c; B B B 由 m p m\times p mp 组成&#xff0c;详见下。 A [ a 1 , 1 , a 1 , 2 , a 1 , 3 ⋯ a 1 , m a 2 , 1 , a 2 , 2 , a 2 , 3 ⋯ a 2 , m ⋅ ⋅ ⋅ a n , …

javaSE知识点整理总结(上)

目录 一、面向对象 1. 类、对象、方法 2.面向对象三大特征 &#xff08;1&#xff09;封装 &#xff08;2&#xff09;继承 &#xff08;3&#xff09;多态 二、常用类 1.Object类 2.Array类 3.基本数据类型包装类 4.String类 5.StringBuffer类 6.Math类 7.Random…

摄影楼电子相册打开的正确方式,快来看看

​随着科技的不断发展&#xff0c;电子相册已经成为许多人存储和分享照片的重要方式。然而&#xff0c;你知道如何正确打开电子相册吗&#xff1f;今天&#xff0c;我就来教大家一下电子相册的正确打开方式&#xff0c;快来学习一下吧&#xff01; 第一步&#xff1a;选择合适的…

QT拖放事件之七:子类化QMimeData,实现对多个自定义类型进行数据

1、前提说明 /*自定义的MIME类型数据存储在QMimeData对象中, 存在两种方法:1. setData(...)可以把自定义类型的数据以QByteArray的形式直接存储在QMimeData中,但是使用此方法一次只能对一个MIME类型进行处理(可参考 QT拖放事件六:自定义MIME类型的存储及读取demo ) 一文。…

成立近30年,它如何找到政企采购突破点?

回看中国采购行业的发展&#xff0c;大致可以被分为四个阶段&#xff1a;上世纪90年代的传统采购时代、本世纪初的ERP采购时代、近10年的SRM采购时代以及2018年以来开启的数字化采购时代。近年来&#xff0c;大数据、人工智能和物联网的高速发展&#xff0c;为采购信息化提供底…

从探头到传感器:德思特数字化仪的全面结合与应用

电压探头可以用于转换信号电平、改变阻抗或提供更方便的连接方法。而包括电流探头、加速度计和光电倍增管在内的传感器或变送器&#xff0c;则可以将各种物理量转换为电信号。这两种输入设备都受到德思特数字化仪的支持。这篇应用笔记将介绍如何将德思特板卡式数字化仪和探头、…

一文2000字记录基于jmeter+perfmon的稳定性测试

01、任务情况 1、任务总览 本次平台稳定性测试的目的在于&#xff1a;在服务器压力处于较饱和&#xff08;达到80%系统最大TPS&#xff09;压力之下&#xff0c;在较长时间&#xff08;>8小时&#xff09;之内观测服务器稳定性问题&#xff0c;以及资源使用情况和异常。 …

springcloud-gateway 路由加载流程

问题 Spring Cloud Gateway版本是2.2.9.RELEASE&#xff0c;原本项目中依赖服务自动发现来自动配置路由到微服务的&#xff0c;但是发现将spring.cloud.gateway.discovery.locator.enabledfalse 启动之后Gateway依然会将所有微服务自动注册到路由中&#xff0c;百思不得其解&a…

【仿真建模-anylogic】开发规范

Author&#xff1a;赵志乾 Date&#xff1a;2024-06-28 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 0. 说明 实际模型开发过程中&#xff0c;对遇到的问题进行总结归纳出以下开发规范&#xff0c;仅供参考&#xff01; 1. 强制性规范 1…

pcr实验室和P2实验室装修设计中的区别

PCR实验室和P2实验室在装修设计的区别是什么&#xff1f;PCR实验室指的是基因扩增实验室&#xff0c;而P2实验室是指生物安全实验室中的一个分类&#xff0c;是生物安全防护达到二级的实验室。那么PCR实验室和P2实验室装修设计标准是什么&#xff1f;实验室装修公司小编为您详解…

数据分析三剑客-Matplotlib

数据分析三剑客 数据分析三剑客通常指的是在Python数据分析领域中&#xff0c;三个非常重要的工具和库&#xff1a;Pandas、NumPy和Matplotlib。Pandas主要负责数据处理和分析&#xff0c;NumPy专注于数值计算和数学运算&#xff0c;而Matplotlib则负责数据可视化。这三个库相…

动手学深度学习(Pytorch版)代码实践 -计算机视觉-44目标检测算法综述:R-CNN、SSD和YOLO

41~44目标检测算法综述&#xff1a;R-CNN、SSD和YOLO 1. 区域卷积神经网络 (R-CNN 系列) 1.1 R-CNN 使用启发式搜索算法来选择锚框。使用预训练模型对每个锚框提取特征&#xff08;每个锚框视为一张图片&#xff0c;使用 CNN 提取特征&#xff09;。训练 SVM 进行类别分类&a…

计算机体系结构 量化研究方法

在第一章中看到关于微处理器中dynamic energy 和 dynamic power的定义觉得有些奇怪&#xff0c;特别记录一下。 上面的定义是取决于上下文的&#xff1a;动态能量可以理解为在一个时钟周期内&#xff0c;由电容充放电消耗的能量总和&#xff0c;而动态功率则是这种能量消耗在单…

Vite脚手架+Vant组件库初始化前端项目

脚手架概念&#xff1a; 在前端开发中&#xff0c;脚手架&#xff08;Scaffold&#xff09;是指一个用于快速搭建项目基础结构的工具或模板。脚手架包含了项目所需的基本文件结构、配置文件、依赖管理等内容&#xff0c;使开发者能够更快速地开始项目开发&#xff0c;而不必从…

常微分方程算法之编程示例四(龙格-库塔法)

目录 一、算例一 1.1 研究问题 1.2 C++代码 1.3 计算结果 二、算例二 2.1 研究问题 2.2 C++代码 2.3 计算结果 一、算例一 本节我们采用龙格-库塔法(Runge-Kutta法)求解算例。 龙格-库塔法的原理及推导请参考: 常微分方程算法之龙格-库塔法(Runge-Kutta法)…

经验分享之会员 SaaS 系统

前言 2018年&#xff0c;这是不平凡的一年&#xff1b;互联网行业的中台战略、会员经济等模式如火如荼&#xff0c;同时也逐渐地走入我们公司每个人的视野。在南海集团的战略规划背景下&#xff0c;当时我所在的公司作为集团的研发中心&#xff0c;承担了对会员 SaaS 系统的建…

【小程序静态页面】猜拳游戏大转盘积分游戏小程序前端模板源码

猜拳游戏大转盘积分游戏小程序前端模板源码&#xff0c; 一共五个静态页面&#xff0c;首页、任务列表、大转盘和猜拳等五个页面。 主要是通过做任务来获取积分&#xff0c;积分可以兑换商品&#xff0c;也可用来玩游戏&#xff1b;通过玩游戏既可能获取奖品或积分也可能会消…

赛盈分销谈烧烤市场的未来,论创新与差异化出海的重要性!

过去几年里&#xff0c;海外旅游市场格外热闹&#xff0c;不仅景点火爆&#xff0c;露营烧烤活动也更加频繁&#xff0c;而这也催生了烧烤设备的市场增长。 全球烧烤用具市场在去年就达到了265.8亿美元&#xff0c;同比增长20.3%&#xff0c;Statista数据预测到2027年将超过515…

MySQL事务——Java全栈知识(31)

1、事务的特性 原子性&#xff08;Atomicity&#xff09;&#xff1a;事务是不可分割的最小操作单元&#xff0c;要么全部成功&#xff0c;要么全部失败。 一致性&#xff08;Consistency&#xff09;&#xff1a;事务完成时&#xff0c;必须使所有的数据都保持一致状态。 隔离…