c++中串口的安全封装使用

固定缓冲区大小:在这种情况下,你将缓冲区大小固定为4096字节。如果你的数据量可能超过这个限制,可能需要反复调用读取操作以确保读取完整的数据。

局部变量初始化:在C++中,局部变量如果不是内置类型(如int、char等),编译器会自动调用其默认构造函数进行初始化。对于内置类型,如果不显式初始化,它们的值是未定义的,可能包含任何内容。在你的代码中,buffer是一个字符数组,不需要显式初始化,因为你马上就会用::read函数把数据填充进去。

错误处理:::read函数可能会返回负值,以指示读取失败。你应该检查bytes_read是否为负值,并相应地处理错误情况。

字符串构造:如果::read返回负值,那么std::string(buffer, bytes_read)中的bytes_read将是负值,这会导致未定义行为。你需要确保bytes_read是非负的。

综合这些考虑,可以改进你的代码如下:

cpp
#include
#include
#include
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include

class ThreadSafeSerialPort {
public:
ThreadSafeSerialPort(const std::string& port_name, int baud_rate) {
fd_ = open(port_name.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
if (fd_ < 0) {
throw std::runtime_error(“Failed to open serial port”);
}

    struct termios tty;memset(&tty, 0, sizeof tty);if (tcgetattr(fd_, &tty) != 0) {close(fd_);throw std::runtime_error("Failed to get terminal attributes");}cfsetospeed(&tty, baud_rate);cfsetispeed(&tty, baud_rate);tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit charstty.c_iflag &= ~IGNBRK; // disable break processingtty.c_lflag = 0; // no signaling chars, no echo, no canonical processingtty.c_oflag = 0; // no remapping, no delaystty.c_cc[VMIN]  = 1; // read doesn't blocktty.c_cc[VTIME] = 5; // 0.5 seconds read timeouttty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrltty.c_cflag |= (CLOCAL | CREAD); // ignore modem controls, enable readingtty.c_cflag &= ~(PARENB | PARODD); // shut off paritytty.c_cflag &= ~CSTOPB;tty.c_cflag &= ~CRTSCTS;if (tcsetattr(fd_, TCSANOW, &tty) != 0) {close(fd_);throw std::runtime_error("Failed to set terminal attributes");}
}~ThreadSafeSerialPort() {close(fd_);
}void write(const std::string& data) {std::lock_guard<std::mutex> guard(mutex_);::write(fd_, data.c_str(), data.size());
}std::string read() {std::lock_guard<std::mutex> guard(mutex_);const size_t buffer_size = 4096; // 设定一个固定的缓冲区大小char buffer[buffer_size];ssize_t bytes_read = ::read(fd_, buffer, buffer_size);if (bytes_read < 0) {throw std::runtime_error("Failed to read from serial port");}return std::string(buffer, bytes_read);
}

private:
int fd_;
std::mutex mutex_;
};
使用示例
cpp
#include
#include

int main() {
try {
// 创建线程安全的串口对象
ThreadSafeSerialPort serial_port(“/dev/ttyUSB0”, B9600);

    // 创建一个线程进行写操作std::thread writer([&]() {while (true) {std::string data_to_write = "Hello Serial\n";serial_port.write(data_to_write);std::this_thread::sleep_for(std::chrono::seconds(1));}});// 创建另一个线程进行读操作std::thread reader([&]() {while (true) {try {std::string data_read = serial_port.read(); // 使用新的读取方法if (!data_read.empty()) {std::cout << "Read: " << data_read << std::endl;}} catch (const std::exception& ex) {std::cerr << "Error: " << ex.what() << std::endl;}std::this_thread::sleep_for(std::chrono::milliseconds(500));}});// 等待线程结束writer.join();reader.join();} catch (const std::exception& ex) {std::cerr << "Error: " << ex.what() << std::endl;
}return 0;

}
在上述代码中,我添加了对read函数返回值的检查,以确保没有发生错误。如果::read返回负值,我们将抛出一个异常,以指示读取失败。这种方式在多线程环境中能够更好地处理错误,并提高代码的健壮性。

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

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

相关文章

Java基础——String类详解,实用解释

String类(不是基本数据类型) - String的不可变性 在 Java 8 中&#xff0c; String 内部使用 char 数组存储数据。并且被声明为 final &#xff0c;因此它不可被继承。 public final class String implements java.io.Serializable, Comparable<String>, CharSequence…

记忆化搜索——AcWing 901. 滑雪

记忆化搜索 定义 记忆化搜索是一种结合了搜索和动态规划思想的方法。它通过将已经计算过的结果存储起来&#xff0c;在后续遇到相同情况时直接返回存储的结果&#xff0c;避免重复计算。 运用情况 当问题可以用递归方式求解&#xff0c;但存在大量重复计算时。一些复杂的组…

python从入门到精通3:变量

在Python编程中&#xff0c;变量是一个非常重要的概念。它们用于存储数据&#xff0c;并在程序执行过程中进行数据的读取、修改和传递。理解变量的概念、命名规则、数据类型以及作用域&#xff0c;对于编写高效、健壮的Python代码至关重要。下面&#xff0c;我们将对Python变量…

收藏||电商数据采集流程||电商数据采集API接口

商务数据分析的流程 第一步&#xff1a;明确分析目的。首先要明确分析目的&#xff0c;并把分析目的分解成若干个不同的分析要点&#xff0c;然后梳理分析思路&#xff0c;最后搭建分析框架。 第二步&#xff1a;数据采集。主流电商API接口数据采集&#xff0c;一般可以通过数…

集装箱超重问题怎么解决一文读懂‼️

超重处理与限重政策详解 在国际海运过程中&#xff0c;集装箱超重会面临不同的处理方式和限制政策。以下是详细解析&#xff1a; 一、超重处理 船公司超重处理&#xff1a; 补交超重费&#xff1a;与船公司协商&#xff0c;补交超重费即可正常运输。 港区超重处理&#xff1a;…

顶顶通呼叫中心中间件-私有化asrproxy安装指南

一、安装asrproxy 上传asrproxy安装包到服务器目录&#xff1a;/root 上传完成之后依次执行下面的命令即可依次执行以下命令 cd ~mkdir -p /ddt/asrproxyunzip asrproxy_*.zip -d /ddt/asrproxycd /ddt/asrproxychmod x installlib.sh./installlib.shchmod x asrproxychmod x…

浪潮(Inspur)服务器硬件监控指标解读

随着企业业务的快速发展&#xff0c;服务器的稳定运行成为保障业务连续性的关键。浪潮&#xff08;Inspur&#xff09;服务器以其卓越的性能和稳定性&#xff0c;在数据中心中扮演着重要角色。 为了确保服务器的稳定运行&#xff0c;监控易作为一款专业的IT基础设施监控软件&am…

工控巨头去年业绩飙升10%,今年250亿出售子业务给美国黑石集团,意欲何为?...

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 更多的海量【智能制造】相关资料&#xff0c;请到智能制造online知识星球自行下载。 在工业自动化领域&#xff0c;艾默生一直以其卓越的技术和强…

互联网摸鱼日报(2024-06-21)

互联网摸鱼日报(2024-06-21) 36氪新闻 「宁王们」出海&#xff0c;钉钉造船 时机已经成熟&#xff0c;“电竞入奥”这次似乎真的要成了 快充与电池容量齐飞&#xff0c;手机体验才能更加均衡 上万块买片叶子&#xff0c;热带植物成为新式潮玩 让哈弗H6破防的价格战&#x…

C++ - 介绍enum的使用

在 C 中&#xff0c;枚举关键字用于定义枚举&#xff0c;枚举是一种用户定义的数据类型&#xff0c;由一组命名的积分常量组成。枚举可以用有意义的名称来表示相关常量的集合&#xff0c;从而提高代码的可读性和可维护性。 In C, the enum keyword is used to define an enumer…

CubeFS - 新一代云原生存储系统

CubeFS 是一种新一代云原生存储系统,支持 S3、HDFS 和 POSIX 等访问协议,支持多副本与纠删码两种存储引擎,为用户提供多租户、 多 AZ 部署以及跨区域复制等多种特性。 官方文档 CubeFS 作为一个云原生的分布式存储平台,提供了多种访问协议,因此其应用场景也非常广泛,下面…

驱动芯片退饱和保护(DESAT)

短路测试和双脉冲测试。 功率模块的短路承受能力的评估分为短路时间评估和短路能量评估两大类。短路时间由短路检测时间与短路关断时间共同构成 短路检测需要兼顾时效性与抗扰性能&#xff0c;要求系统能够及时响应&#xff0c;避免功率模块损坏。同时能够屏蔽开关过程的干扰…

车辆轨迹预测系列 (一):轨迹预测方法综述解析

文章目录 车辆轨迹预测系列 (一)&#xff1a;轨迹预测方法综述解析1、Contextual FactorsPhysics-related factors (物理相关因素):Road-related factors (道路相关因素):Interaction-related factors (交互相关因素): 2、Output TypesUnimodal Trajectory Prediction(单一模式…

AI音乐大模型:是创意的助力还是产业的挑战?

近期音乐界迎来了一场前所未有的革命。随着多家科技公司纷纷推出音乐大模型&#xff0c;素人生产音乐的门槛被前所未有地拉低&#xff0c;一个崭新的“全民音乐时代”似乎已近在眼前。然而&#xff0c;在这场技术革新的浪潮中&#xff0c;关于AI产品版权归属、创意产业如何在AI…

前端深拷贝非常优质的函数,包含函数、循环引用,Set、Map、Date、自定义构造函数等处理

前端深拷贝 前端深拷贝非常优质的函数&#xff0c;包含函数、循环引用&#xff0c;Set、Map、Date、自定义构造函数等处理 function deepClone(obj: any, hash new WeakMap()): any {if (Object(obj) ! obj) return obj // 处理基础类型if (hash.has(obj)) return hash.get(…

Python Web实战:Python+Django+MySQL实现基于Web版的增删改查

项目实战 1.创建项目(sms) File->New Project->Django 稍等片刻&#xff0c;项目的目录结构如下图 项目创建后确认是否已安装Django和mysqlclient解释器&#xff0c;如何确认&#xff1f;file->Settings 如果没有请在Terminal终端输入以下命令完成安装 pip instal…

C++初学者指南第一步---5.介绍std::vector

C初学者指南第一步—5.介绍std::vector 目录 C初学者指南第一步---5.介绍std::vector1.初始化/访问2.添加元素3.Resizing调整大小4.在尾部删除元素5. 复制一直是深拷贝&#xff01; 注意std代表C标准库的命名空间&#xff0c;vector&#xff08;向量&#xff09;是标准库中的一…

18V-180V降5V500mA恒压WT5118

18V-180V降5V500mA恒压WT5118 如何实现18V-180V宽电压输入下的恒压5V 500mA输出。输入电压是波动的18V还是高达180V,WT5118都能确保输出端提供稳定的5V电压和500mA的电流。 WT5118 是一款集成了 180V 高电压 MOSFET 的 DC-DC 控制器&#xff0c;专为开关电源设计。该设备具备内…

数字孪生智慧应用场景——数字孪生智慧城市各行业领域应用场景学习参考资料

下面资源来源于网络&#xff0c;如有侵权请联络删除&#xff01; 数字孪生技术&#xff0c;作为近年来科技领域的热门话题&#xff0c;其发展情况与应用领域正不断拓展深化。简单来说&#xff0c;数字孪生技术是通过构建一个与物理实体相对应的虚拟模型&#xff0c;实现对物理世…

国产化ETL产品必备的特性(非开源包装)

ETL负责将分布的、异构数据源中的数据如关系数据、平面数据文件等抽取到临时中间层后进行抽取、清洗&#xff08;净化&#xff09;、转换、装载、标准、集成&#xff08;汇总&#xff09;...... 最后加载到数据仓库或数据集市中&#xff0c;成为联机分析处理、数据挖掘的基础。…