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

CSerialPort教程4.3.x (2) - CSerialPort源码简介

CSerialPort教程4.3.x (2) - CSerialPort源码简介

前言

CSerialPort项目是一个基于C/C++的轻量级开源跨平台串口类库,可以轻松实现跨平台多操作系统的串口读写,同时还支持C#, Java, Python, Node.js等。

CSerialPort项目的开源协议自 V3.0.0.171216 版本后采用GNU Lesser General Public License v3.0

为了让开发者更好的使用CSerialPort进行开发,特编写基于4.3.x版本的CSerialPort教程系列。

CSerialPort项目地址:

  • https://github.com/itas109/CSerialPort
  • https://gitee.com/itas109/CSerialPort

本文对CSerialPort 4.3.0版本源码进行简介。

1. CSerialPort源码目录结构

CSerialPort # root
+--- .clang-format # code format 代码规范
├── bindings # 第三方语言接口
│   ├── c # c interface c接口
│   ├── csharp # csharp interface c#接口
│   ├── java # java interface java接口
│   ├── javascript # javascript interface javascript接口
│   └── python # python interface python接口
├── CHANGELOG.md # change log 修改日志
├── cmake # cross compile 交叉编译
├── CMakeLists.txt
├── doc # document 文档
├── examples # example 示例程序
│   ├── CommMFC # CSerialPort MFC Demo MFC程序示例
│   ├── CommNoGui # CSerialPort No Gui Demo 无界面程序示例
│   ├── CommQT # CSerialPort QT Demo QT程序示例
│   ├── CommTui # CSerialPort tui Demo 文本界面程序示例
│   ├── CommWXWidgets # CSerialPort wxwidgets Demo wxwidgets界面程序示例
├── include # headers 头文件
│   └── CSerialPort
│       ├── ibuffer.hpp # lightweight cross-platform buffer library 轻量级跨平台缓冲区类
│       ├── ithread.hpp # lightweight cross-platform thread library 轻量级跨平台线程类
│       ├── itimer.hpp # lightweight cross-platform timer library 轻量级跨平台定时器类
│       ├── iutils.hpp # lightweight cross-platform utils library 轻量级跨平台工具类
│       ├── SerialPortBase.h # CSerialPort Base class 串口基类
│       ├── SerialPort_global.h # Global difine of CSerialPort 串口全局定义 
│       ├── SerialPort.h # lightweight cross-platform serial port library 轻量级跨平台串口类库
│       ├── SerialPortInfoBase.h # CSerialPortInfo Base class 串口信息辅助类基类
│       ├── SerialPortInfo.h # CSerialPortInfo class 串口信息辅助类
│       ├── SerialPortInfoUnixBase.h # CSerialPortInfo unix class unix串口信息辅助类基类
│       ├── SerialPortInfoWinBase.h # CSerialPortInfo windows class windows串口信息辅助类基类
│       ├── SerialPortListener.h # CSerialPortListener interface class 串口事件监听接口类
│       ├── SerialPortUnixBase.h # CSerialPort unix Base class unix串口基类
│       ├── SerialPort_version.h # CSerialPort version 版本定义
│       └── SerialPortWinBase.h # CSerialPort Windows Base class windows串口基类
├── lib # lib 库目录
├── LICENSE # LGPL3.0 license
├── pic # picture 图片
├── README.md
├── README_zh_CN.md
├── src # source 源代码
├── test # unit test 单元测试
└── VERSION # version 版本号

2. CSerialPort常用函数

2.1 串口信息相关函数

2.1.1 获取串口信息列表函数 availablePortInfos

该函数获取串口信息列表,主要包括:

  • 串口名称 (如COM2)
  • 描述信息 (如USB-SERIAL CH340)
  • 硬件id (如USB\VID_1A86&PID_7523&REV_0264)
static vector<SerialPortInfo> itas109::CSerialPortInfo::availablePortInfos()

2.2 串口操作相关函数

2.2.1 串口初始化函数 init

该函数用于串口初始化。

void itas109::CSerialPort::init(const char *portName,                                 // 串口名称 Windows:COM1 Linux:/dev/ttyS0int baudRate = itas109::BaudRate9600,                 // 波特率itas109::Parity parity = itas109::ParityNone,         // 校验位itas109::DataBits dataBits = itas109::DataBits8,      // 数据位itas109::StopBits stopbits = itas109::StopOne,        // 停止位itas109::FlowControl flowControl = itas109::FlowNone, // 流控制unsigned int readBufferSize = 4096                    // 读取缓冲区大小
)

注意:

  • 5位数据位不能使用2位停止位
  • 1.5位停止位不能使用5位数据位
  • POSIX系统8位数据位不能使用0校验
  • windows数据位范围为4 - 8
  • 1.5位停止位仅对windows有效
  • 停止位数字1表示StopOneAndHalf,即1.5位停止位,并非1位停止位

2.2.2 打开串口函数 open

该函数用于打开串口。

bool itas109::CSerialPort::open()

true表示打开成功,false表示打开失败。

打开失败可用itas109::CSerialPort::getLastError()获取错误码

2.2.3 关闭串口函数 close

该函数用于关闭串口。

void itas109::CSerialPort::close()

2.2.4 是否打开串口成功函数 isOpen

该函数用于获取是否打开串口成功。

bool itas109::CSerialPort::isOpen()

true表示串口打开成功,false表示串口打开失败。

2.2.5 向串口写入数据函数 writeData

该函数用于向串口写入数据。

int itas109::CSerialPort::writeData(const void *data, // 待写入数据int maxSize       // 写入长度
)

成功则返回写入字节数,失败则返回-1。

写入失败可用itas109::CSerialPort::getLastError()获取错误码。

2.2.6 从串口读取指定长度数据函数 readData

该函数用于从串口读取指定长度数据。

int readData(void *data,  // 读取结果int size     // 读取长度
)

正常则返回读取字节数,失败则返回-1。

读取失败可用itas109::CSerialPort::getLastError()获取错误码。

注意:
CSerialPort异步操作模式下,需要配合connectReadEvent函数使用。详见第三节的代码示例。

2.2.7 从串口读取所有数据函数 readAllData

该函数用于从串口读取所有数据。

int itas109::CSerialPort::readAllData(void *data // 读取结果
)

正常则返回读取字节数,失败则返回-1。

读取失败可用itas109::CSerialPort::getLastError()获取错误码。

注意:
CSerialPort异步操作模式下,需要配合connectReadEvent函数使用。详见第三节的代码示例。

2.2.8 绑定读取事件函数 connectReadEvent

该函数用于异步模式(默认)下,绑定读取响应的结果。

需要继承CSerialPortListener,并实现onReadEvent虚函数。详见第三节的代码示例。

class MyListener : public CSerialPortListener
{
public:void onReadEvent(const char *portName, unsigned int readBufferLen){}
}

2.2.9 获取CSerialPort版本信息函数 getVersion

该函数用于获取CSerialPort版本信息。

std::string itas109::CSerialPort::getVersion()

返回CSerialPort版本信息,如https://github.com/itas109/CSerialPort - V4.3.0.230215

2.2.10 错误码 SerialPortError

错误码数值错误码宏定义错误码说明
-1ErrorUnknownunknown error 未知错误
0ErrorOKok 成功
1ErrorFailgeneral error一般性错误
2ErrorNotImplementednot implemented 未实现
3ErrorInnerinner error 内部错误(如内存访问异常等)
4ErrorNullPointernull pointer error 空指针错误
5ErrorInvalidParaminvalid parameter error 无效的参数
6ErrorAccessDeniedaccess denied error 权限错误
7ErrorOutOfMemoryout of memory 内存不足
8ErrorTimeouttime out error 超时
9ErrorNotInitnot init 未初始化
10ErrorInitFailedinit failed 初始化失败
11ErrorAlreadyExistalready exist 已经存在
12ErrorNotExistnot exist 不存在
13ErrorAlreadyOpenalready open 已经打开
14ErrorNotOpennot open 未打开
15ErrorOpenFailedopen failed 打开失败
16ErrorCloseFailedclose failed 关闭失败
17ErrorWriteFailedwrite failed 写入失败
18ErrorReadFailedread failed 读取失败

3. CSerialPort简单代码示例

  • 操作步骤
$ mkdir CSerialPortDemo
$ cd CSerialPortDemo
$ git clone https://github.com/itas109/CSerialPort
$ touch CSerialPortDemo.cpp
$ touch CMakeLists.txt
$ mkdir bin 
$ cd bin
$ cmake ..
$ cmake --build .
  • 目录结构
$ tree
.
+--- CMakeLists.txt
+--- CSerialPort
|   +--- include
|   +--- src
|   +--- ...
+--- CSerialPortDemo.cpp
  • CSerialPortDemo.cpp

注意:接收函数需要继承CSerialPortListener

#include <iostream>#include "CSerialPort/SerialPort.h"
#include "CSerialPort/SerialPortInfo.h"#include <vector>
using namespace itas109;
using namespace std;class MyListener : public CSerialPortListener
{
public:MyListener(CSerialPort *sp): p_sp(sp){};void onReadEvent(const char *portName, unsigned int readBufferLen){if (readBufferLen > 0){char *data = new char[readBufferLen + 1]; // '\0'if (data){// readint recLen = p_sp->readData(data, readBufferLen);if (recLen > 0){data[recLen] = '\0';std::cout << portName << ", Length: " << recLen << ", Str: " << data << std::endl;}delete[] data;data = NULL;}}};private:CSerialPort *p_sp;
};int main()
{CSerialPort sp;MyListener listener(&sp);std::cout << "Version : " << sp.getVersion() << std::endl << std::endl;vector<SerialPortInfo> m_availablePortsList = CSerialPortInfo::availablePortInfos();std::cout << "availableFriendlyPorts: " << std::endl;for (size_t i = 1; i <= m_availablePortsList.size(); ++i){SerialPortInfo serialPortInfo = m_availablePortsList[i - 1];std::cout << i << " - " << serialPortInfo.portName << " " << serialPortInfo.description << " " << serialPortInfo.hardwareId << std::endl;}if (m_availablePortsList.size() == 0){std::cout << "No valid port" << std::endl;}else{std::cout << std::endl;int input = -1;do{std::cout << "Please Input The Index Of Port(1 - " << m_availablePortsList.size() << ")" << std::endl;std::cin >> input;if (input >= 1 && input <= m_availablePortsList.size()){break;}} while (true);const char *portName = m_availablePortsList[input - 1].portName;std::cout << "Port Name: " << portName << std::endl;sp.init(portName,              // windows:COM1 Linux:/dev/ttyS0itas109::BaudRate9600, // baudrateitas109::ParityNone,   // parityitas109::DataBits8,    // data bititas109::StopOne,      // stop bititas109::FlowNone,     // flow4096                   // read buffer size);sp.setReadIntervalTimeout(0); // read interval timeout 0ms// sp.setOperateMode(itas109::SynchronousOperate);sp.open();std::cout << "Open " << portName << (sp.isOpen() ? " Success. " : " Failed. ");std::cout << "Code: " << sp.getLastError() << ", Message: " << sp.getLastErrorMsg() << std::endl;// 绑定读取函数sp.connectReadEvent(&listener);// 写入数据sp.writeData("itas109", 7);for (;;){}}return 0;
}
  • CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)project(CSerialPortDemo)if(APPLE)find_library(IOKIT_LIBRARY IOKit)find_library(FOUNDATION_LIBRARY Foundation)
endif()include_directories(CSerialPort/include)
file(GLOB_RECURSE COMMON_SOURCES CSerialPort/src/SerialPort.cpp CSerialPort/src/SerialPortBase.cpp CSerialPort/src/SerialPortInfo.cpp CSerialPort/src/SerialPortInfoBase.cpp)
if (CMAKE_HOST_WIN32)file(GLOB_RECURSE OS_ABOUT_SOURCES CSerialPort/src/SerialPortInfoWinBase.cpp CSerialPort/src/SerialPortWinBase.cpp)
elseif (CMAKE_HOST_UNIX)file(GLOB_RECURSE OS_ABOUT_SOURCES CSerialPort/src/SerialPortInfoUnixBase.cpp CSerialPort/src/SerialPortUnixBase.cpp)
endif ()	add_executable( ${PROJECT_NAME} CSerialPortDemo.cpp ${COMMON_SOURCES} ${OS_ABOUT_SOURCES})if (WIN32)target_link_libraries( ${PROJECT_NAME} setupapi )
elseif (APPLE)target_link_libraries( ${PROJECT_NAME} ${FOUNDATION_LIBRARY} ${IOKIT_LIBRARY})
elseif (UNIX)target_link_libraries( ${PROJECT_NAME} pthread )
endif ()
  • 运行结果(windows下环回测试)
Version : https://github.com/itas109/CSerialPort - V4.3.0.230215availableFriendlyPorts:
1 - COM1 USB-SERIAL CH340  USB\VID_1A86&PID_7523&REV_0264Please Input The Index Of Port(1 - 1)
1
Port Name: COM1
Open COM1 Success. Code: 0, Message: success
COM1, Length: 7, Str: itas109

License

License under CC BY-NC-ND 4.0: 署名-非商业使用-禁止演绎


Reference:

  1. https://github.com/itas109/CSerialPort
  2. https://gitee.com/itas109/CSerialPort
  3. https://blog.csdn.net/itas109

相关文章:

CSerialPort教程4.3.x (2) - CSerialPort源码简介

CSerialPort教程4.3.x (2) - CSerialPort源码简介 前言 CSerialPort项目是一个基于C/C的轻量级开源跨平台串口类库&#xff0c;可以轻松实现跨平台多操作系统的串口读写&#xff0c;同时还支持C#, Java, Python, Node.js等。 CSerialPort项目的开源协议自 V3.0.0.171216 版本…...

【数据结构OJ题】有效的括号

原题链接&#xff1a;https://leetcode.cn/problems/valid-parentheses/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 这道题目主要考查了栈的特性&#xff1a; 题目的意思主要是要做到3点匹配&#xff1a;类型、顺序、数量。 题目给的例子是比较…...

Java性能分析中常用命令和工具

当涉及到 Java 性能分析时&#xff0c;有一系列强大的命令和工具可以帮助开发人员分析应用程序的性能瓶颈、内存使用情况和线程问题。以下是一些常用的 Java 性能分析命令和工具&#xff0c;以及它们的详细说明和示例。 以下是一些常用的性能分析命令和工具汇总&#xff1a; …...

JVM性能分析-jstat工具观察gc频率

jstat jstat是java自带的工具&#xff0c;在bin目录下 用法 语法&#xff1a;jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]] [kqkyyj-2 bin]$ jstat -help Usage: jstat -help|-optionsjstat -<option> [-t] [-h&l…...

mysql 查询报错 1267 - Illegal mix of collations

mysql 查询报错 1267 - Illegal mix of collations 详细报错: 1267 - Illegal mix of collations (utf8mb4_0900_ai_ci,IMPLICIT) and (utf8mb4_unicode_ci,IMPLICIT) for 主要的原因其实就是两张表的字符集不一样改一下就行了。 注: 改了表还是报错的话,那就是表内的字段没有…...

【ARM】Day6

cotex-A7核UART总线实验 1. 键盘输入一个字符‘a’&#xff0c;串口工具显示‘b’ 2. 键盘输入一个字符串"nihao"&#xff0c;串口工具显示“nihao” uart.h #ifndef __UART4_H__ #define __UART4_H__#include "stm32mp1xx_rcc.h" #include "stm3…...

深入理解Flink Mailbox线程模型

文章目录 整体设计processMail1.Checkpoint Tigger2.ProcessingTime Timer Trigger processInput兼容SourceStreamTask 整体设计 Mailbox线程模型通过引入阻塞队列配合一个Mailbox线程的方式&#xff0c;可以轻松修改StreamTask内部状态的修改。Checkpoint、ProcessingTime Ti…...

Docker搭建LNMP运行Wordpress平台

一、项目1.1 项目环境1.2 服务器环境1.3 任务需求 二、Linux 系统基础镜像三、Nginx1、建立工作目录2、编写 Dockerfile 脚本3、准备 nginx.conf 配置文件4、生成镜像5、创建自定义网络6、启动镜像容器7、验证 nginx 四、Mysql1、建立工作目录2、编写 Dockerfile3、准备 my.cnf…...

10个常见渐变交互效果

1、透明度渐变背景交互 <div class"fade-background"></div> Copy .fade-background {width: 200px;height: 200px;background: linear-gradient(to bottom, rgba(255, 0, 0, 0), rgba(255, 0, 0, 1));transition: background 0.5s ease; }.fade-backgro…...

[线程/C]基础

文章目录 1. 线程介绍2. 创建线程2.1 线程函数2.2 创建线程 3. 线程退出4. 线程回收4.1 线程函数4.2 回收子线程数据4.2.1 使用子线程栈4.2.2 使用全局变量4.2.3 使用主线程栈 5. 线程分离6. 其他线程函数6.1 线程取消6.2 线程ID的比较 1. 线程介绍 线程是轻量级的进程&#x…...

Spring Clould 负载均衡 - Ribbon

视频地址&#xff1a;微服务&#xff08;SpringCloudRabbitMQDockerRedis搜索分布式&#xff09; Ribbon-负载均衡原理&#xff08;P14&#xff09; 具体实现时通过LoaBalanced注解实现&#xff0c;表示RestTemplate要被Ribbon拦截处理 orderservice调用user时候&#xff0c…...

活用DNS技术实现相同IP的不同端口映射不同域名

WindowsDNS基本配置 在内网的 Windows 服务器环境中&#xff0c;你可以通过配置 DNS 服务和 Web 服务器来实现所需的域名解析和端口转发。如下是一些基本的步骤来实现配置&#xff1a; 1&#xff0c;配置 Windows DNS 服务 在你的 Windows 服务器上配置 DNS 服务&#xff0c…...

AutoHotkey:定时删除目录下指定分钟以前的文件,带UI界面

删除指定目录下&#xff0c;所有在某个指定分钟以前的文件&#xff0c;可以用来清理经常生成很多文件的目录&#xff0c;但又需要保留最新的一部分文件 支持拖放目录到界面 能够记忆设置&#xff0c;下次启动后不用重新设置&#xff0c;可以直接开始 应用场景比如&#xff1a…...

一文学会sklearn中的交叉验证的方法

前言 在机器学习中&#xff0c;我们经常需要评估模型的性能。而为了准确评估模型的性能&#xff0c;我们需要使用一种有效的评估方法。五折交叉验证&#xff08;5-fold cross-validation&#xff09;就是其中一种常用的模型评估方法&#xff0c;用于评估机器学习模型的性能和泛…...

【MySQL面试题(66道)】

文章目录 MySQL面试题(66道)基础1.什么是内连接、外连接、交叉连接、笛卡尔积呢&#xff1f;2.那 MySQL 的内连接、左连接、右连接有有什么区别&#xff1f;3.说一下数据库的三大范式&#xff1f;4.varchar 与 char 的区别&#xff1f;5.blob 和 text 有什么区别&#xff1f;6.…...

CSSCI、北核期刊投稿指南(2023年更新)

该数据为经管类的期刊投稿指南&#xff0c;包含发表难度&#xff0c;文章数量&#xff0c;影响因子&#xff0c;用户评价等指标。共5份文件&#xff0c;分别为国内所有期刊信息库、投稿指南&#xff08;CSSCI版本、CSSCI扩展版本、北大核刊版本、建议期刊版本&#xff09; 一、…...

构建 NodeJS 影院微服务并使用 docker 部署它(02/4)

一、说明 构建一个微服务的电影网站&#xff0c;需要Docker、NodeJS、MongoDB&#xff0c;这样的案例您见过吗&#xff1f;如果对此有兴趣&#xff0c;您就继续往下看吧。 图片取自网络 — 封面由我制作 这是✌️“构建 NodeJS 影院微服务”系列的第二篇文章。 二、对第一部分的…...

HTML <style> 标签

实例 <html> <head> <style type="text/css"> h1 {color:red} p {color:blue} </style> </head><body> <h1>Header 1</h1> <p>A paragraph.</p> </body> </html>定义和用法 <style>…...

设计模式——迪米特法则

文章目录 基本介绍应用实例应用实例改进迪米特法则注意事项和细节 基本介绍 一个对象应该对其他对象保持最少的了解类与类关系越密切&#xff0c;耦合度越大迪米特法则(Demeter Principle)又叫最少知道原则&#xff0c;即一个类对自己依赖的类知道的越少越好。也就是说&#x…...

区块链基本概念与当前生态简介

区块链是一种去中心化的分布式账本技术&#xff0c;它通过将数据按照时间顺序链接成区块&#xff0c;并使用密码学算法确保数据的安全性和完整性。每个区块包含一定数量的交易记录&#xff0c;而且每个区块都包含了前一个区块的哈希值&#xff0c;这样形成了一个不可篡改的链式…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...

前端高频面试题2:浏览器/计算机网络

本专栏相关链接 前端高频面试题1&#xff1a;HTML/CSS 前端高频面试题2&#xff1a;浏览器/计算机网络 前端高频面试题3&#xff1a;JavaScript 1.什么是强缓存、协商缓存&#xff1f; 强缓存&#xff1a; 当浏览器请求资源时&#xff0c;首先检查本地缓存是否命中。如果命…...

解析两阶段提交与三阶段提交的核心差异及MySQL实现方案

引言 在分布式系统的事务处理中&#xff0c;如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议&#xff08;2PC&#xff09;通过准备阶段与提交阶段的协调机制&#xff0c;以同步决策模式确保事务原子性。其改进版本三阶段提交协议&#xff08;3PC&#xf…...