【linux】串口编程(三)——错误处理
一个程序的优劣,可以从多个角度来判断,错误处理就是其中之一。从代码中的错误处理部分,可以体现出一个程序员的水平和修养。
下面还是以libmodbus为例,总结下串口编程中的错误处理。
【1】基础
【1.1】modbus中错误处理有三种:
typedef enum
{MODBUS_ERROR_RECOVERY_NONE = 0,MODBUS_ERROR_RECOVERY_LINK = (1<<1),MODBUS_ERROR_RECOVERY_PROTOCOL = (1<<2),
} modbus_error_recovery_mode;
详解:
A)MODBUS_ERROR_RECOVERY_NONE:默认值,不处理错误,如果有必要由使用者来处理错误;
B)MODBUS_ERROR_RECOVERY_LINK:超时后尝试重新连接;如果是发送(send)失败,将会一直执行关闭/连接(close/connect)或者睡一段时间并刷新缓冲区(_sleep_and_flush),直到发送成功;如果是监听/接收(select/read)失败,将会执行一次关闭/连接;
C)MODBUS_ERROR_RECOVERY_PROTOCOL:在检查完整性(check_integrity)时,比如CRC校验错误,将会睡一段时间并刷新缓冲区(_sleep_and_flush),
【1.2】modbus中设置错误处理的接口
int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery);
#####【1.3】错误处理时用到的_sleep_and_flush函数详解
int _sleep_and_flush(modbus_t *ctx)
{struct timespec request/*保存将要休眠的时间*/, remaining/*发生中断时,未休眠完的时间*/;//libmodbus中休眠时间默认值是0.5s,可以通过modbus_set_response_timeout来设置request.tv_sec = ctx->response_timeout.tv_sec;request.tv_nsec = ((long int)ctx->response_timeout.tv_usec % 1000000)* 1000;//如果休眠函数出错返回,并且错误原因是中断(EINTR)导致的,将未休眠完的时间赋值给request,继续休眠while (nanosleep(&request, &remaining) == -1 && errno == EINTR)request = remaining;//冲洗(抛弃)输入缓冲区和输出缓冲区return tcflush(ctx->s, TCIOFLUSH);
}
【2】发送时的错误处理
A)write返回-1时表示出错,如果此时错误码errno是如下值之一,则尝试关闭/打开后重新发送:
-EBADF:文件描述符错误
-ECONNRESET:连接被重置,如对方关闭了连接
-EPIPE:管道断开:原因通常是当管道读端没有在读,而管道的写端继续有线程在写,就会造成管道中断。
其他情况,执行_sleep_and_flush来刷新缓冲区,再尝试发送
B)write返回值>0时,还需判断是否全部发送,如果没有,可以将没有发送的数据重新发送,或者全部数据重新发送
C)有一种特殊情况,write时,指定的数据长度本身就是0,可以用来测试连通状态。
libmodbus源码如下
static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)
{int rc;int i;msg_length = ctx->backend->send_msg_pre(msg, msg_length);//计算发送的长度//如果设置MODBUS_ERROR_RECOVERY_LINK模式,发送失败时,会一直尝试发送,直到成功;默认情况下,该模式是关闭的。do {rc = write(ctx->s, msg, msg_length);if (rc == -1) {if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {int saved_errno = errno;if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) {modbus_close(ctx);modbus_connect(ctx);} else {_sleep_and_flush(ctx);}errno = saved_errno;}}} while ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&rc == -1);if (rc > 0 && rc != msg_length) {errno = EMBBADDATA;return -1;}return rc;
}
【3】接收时的错误处理
【3.1】select返回-1
A)超时:errno == ETIMEDOUT,执行_sleep_and_flush(有可能在休眠时间内有数据到达,然后flush将会丢失部分数据)
B)文件描述符错误:errno == EBADF,则关闭后重新打开
【3.2】read错误
A)read返回-1
如果错误码errno为一下值,则关闭后重新打开:
-ECONNRESET:连接被重置,如对方关闭了连接
-ECONNREFUSED:连接被拒绝
-EBADF:文件描述符错误
B)read返回0
可以当成连接被关闭的情况来处理,将errno设置成ECONNRESET后返回;
特殊情况是,read时,指定的长度本身是0,可以用来测试连通状态。
相关文章:

微服务实战之春云与刀客(三)—— 面向接口调用代码结构实例
2019独角兽企业重金招聘Python工程师标准>>> 概述 在上一篇中提到了spring cloud 面向接口调用的开发风格,这一篇会举一个简单的但完整的例子来说明整个代码结构。 代码已上传到 https://github.com/maruixiang/spring-cloud-demo/tree/master/demo1 代码…

如何创建复杂的机器学习项目?
翻译 | 光城责编 | 郭芮转载自CSDN(CSDNnews)scikit-learn提供最先进的机器学习算法。但是,这些算法不能直接用于原始数据。原始数据需要事先进行预处理。因此,除了机器学习算法之外,scikit-learn还提供了一套预处理方…

关闭vmware喇叭报警声
关闭vmware喇叭报警声 在vmware里面安装linux系统后,操作时经常使用tab键或使用VI时经常听到pc speaker突然叫一声,如果正当戴着耳机欣赏音乐,被这么一叫还要吓一跳。下面是解决办法:C:\Documents and Settings\All Users\Applica…

【ubuntu工具】Atom的简介及安装
Atom中文社区:https://atom-china.org/ 知乎atom:https://www.zhihu.com/question/22867204 Atom,是github用nodejs编写的一个编辑器 Atom安装步骤: sudo add-apt-repository ppa:webupd8team/atomsudo aptitude updatesudo a…

破解Win2008口令-ERD6.0
我们在日常使用计算机的过程中,大多都经历过由于忘记口令从而无法进入系统的遭遇。遇到这种问题该如何处理呢?很多朋友一定想到了形形的口令破解工具,这些工具中名气最大的就是ERD Commander Boot CD。 ERD Commander Boot CD是一张可以启动操…

【Qt】Qt5.9.0: error: GL/gl.h: 没有那个文件或目录
重新安装ubuntu,在编译Qt时报错: /home/Qt5.9.0/Examples/Qt-5.9/widgets/widgets/calculator/button.cpp:51: from …/calculator/button.cpp:51: /home/Qt5.9.0/5.9/gcc_64/include/QtGui/qopengl.h:139: error: GL/gl.h: 没有那个文件或目录 解决方…

给Chrome“捉虫”16000个,Google开源bug自检工具
整理 | 一一出品 | AI科技大本营(ID:rgznai100) 在内部开发和使用八年之久,近日,Google 宣布开源 bug 自动化检测工具 ClusterFuzz。ClusterFuzz 是一款提供端到端的自动化模糊测试工具:从错误检测到分类排查&…

小巧的日志记录组件 - 开源研究系列文章
今天给大家带来一个小巧的日志记录组件LogHelper。这个组件是由Log4Net这个组件的由来而来的,不过只是写入.txt文本文件而已。如果能够对大家的项目有帮助那就更好了。 首先,打开.SLN解决方案,添加引用日志组件。 然后,先对日志组…

.NET开发人员值得关注的七个开源项目
微软近几年在.NET社区开源项目方面投入了相当多的时间和资源,不禁让原本对峙的开源社区阵营大吃一惊,从微软.NET社区中的反应来看,微软.NET开发阵营对开源工具的依赖正日益增强,本文就为所有.NET开发人员介绍7个应该关注的开源项目…

SystemTap了解
SystemTrap是监控和跟踪运行中的Linux内核操作的动态方法。 http://www.ibm.com/developerworks/cn/linux/l-systemtap/ 使用SystemTrap需要使用trap来运行一个stp脚本 如何安装: Centos下直接yum install systemtrap就行了 测试是否可以运行 运行:stap …

Windows 95被做成了App,可玩扫雷和纸牌
6 秒重温 Windows95 开机画面 作者 | 琥珀 出品 | AI科技大本营(ID:rgznai100) “看到 Win95,再看到仙剑 DOS 的画面,突然有种想哭的感觉,小时候帮李逍遥实现了仗剑江湖的愿望,但自己却没有实现自己的愿望…

【Ubuntu】虚拟机VirtualBox安装win7完整步骤
在Ubuntu16.04中使用VirtualBox安装win7,亲测可以完美使用; 完整步骤参见如下链接: 1、VirtualBox安装步骤:http://www.xitongcheng.com/jiaocheng/xtazjc_article_23804.html 2、win7镜像下载:http://www.xitongcheng.com/jia…

全栈AI工程师指南,DIY一个识别手写数字的web应用
作者 | shadow chi本文经授权转载自 无界社区mixlab(ID:mix-lab)网上大量教程都是教如何训练模型,往往我们只学会了训练模型,而实际应用的环节是缺失的。def AIFullstack( ):本文从「…

mysql 中limit 用法!!
select * from mydb where id limit i,j; 意思就是从第i行开始,检索出j行,结束!主要用于分页技术中,比如说我们一页现实10行,可以这样做:select * from mydb where id order by id desc limit $page,10($pa…

【Qt】Qt动态库和静态库的创建和使用
动态库(共享库)的创建 在Qt Creator中新建项目,选择Library 点击“Choose”进入下一步 选择创建库的类型:共享库 选择Kit套件 选择需要的模块 配置工程路径、名字等 Qt Creator自动创建的文件 我配置的动态库名字为:Share pro文件内容

23.3. Ethernet0/0 - Wan口配置
23.3.1. DHCP 动态IP地址 <Netkiller>system-view System View: return to User View with CtrlZ.interface Ethernet0/0port link-mode routenat outboundip address dhcp-allocipsec policy navigator #[Netkiller]display dhcp client Ethernet0/0 DHCP client inform…

用Python解锁“吃鸡”正确姿势
大吉大利,今晚吃鸡~ 今天跟朋友玩了几把吃鸡,经历了各种死法,还被嘲笑说论女生吃鸡的100种死法,比如被拳头抡死、跳伞落到房顶边缘摔死 、把吃鸡玩成飞车被车技秀死、被队友用燃烧瓶烧死的。这种游戏对我来说就是一个让我明白原来…

Oracle Grid Control 10.2.0.5 for Linux 安装和配置指南
一、概述:Grid Control的组件包括Management Agent, Management Service (OMS), Management Repository. 系统架构如下: 10g oem是一个基于web的管理架构,这和10g之前的笨重的java客户端有很大的区别。我们可以从2方面来研究它的架构,一个是管…

【Qt】Qt Plugin:Qt插件创建与使用
插件接口设计 以a+b=c的接口为例:int add(int a, int b) 在 主项目 工程中创建接口文件(一个头文件)eg:Add.h #ifndef ADD_H #define ADD_H#include <QtPlugin> class Add { public:virtual int add(int a, int b)= 0;//纯虚函数 }; Q_DECLARE_INTERFACE(Add, &qu…

9.5. SELINUX
禁用SElinux编辑/etc/selinux/config,修改如下内容: SELINUXdisabled使用命令 getenforce setenforce 0lokkit --selinuxdisabledPlease enable JavaScript to view the <a href"http://disqus.com/?ref_noscript">comments powered by…

说说我们为什么需要加班
做软件这行,加班就是家常便饭。做了这么多年程序员,我还真没听哪个说公司不加班的,碰见好的不时、偶尔加班,差的就是无尽的加。加班是那么的邪恶、令人作呕,但又无法抗拒,它仿佛就像嫖客患上梅毒——摆脱不…

为 Django admin 登录页添加验证码
为什么80%的码农都做不了架构师?>>> 历史原因,使用上古版本 django 1.6.5,但新版本应该大同小异 首先添加自定义后台模块app, 如adm,并添加到 INSTALLED_APPS 下。 假设处理自定义登录的view是 apps/adm/v…

手机芯片谁是AI之王?高通、联发科均超华为
整理 | apddd出品 | AI科技大本营(ID:rgznai100)尽管相当数量的人工智能服务,是由云计算网络提供,但在响应低延迟、保护隐私、应用场景等方面,手机AI芯片无可替代。例如人脸解锁,图像增强、识别,…

【linux】error: stdio.h: No such file or directory
ubuntu 默认没有C和C编译环境 ubuntu 默认没有C和C编译环境,新装的ubuntu,使用gcc编译时,会报错,找不到某某头文件等。在编译一个demo,如hello world时,会报错: error: stdio.h: No such file …

SqlParameter的用法
1。一些面例子为例:List<SqlParameter> listp new List<SqlParameter>();listp.Add(new SqlParameter("userid", userid));string sql "select * from userbooks where useriduserid";在执行sql语句时 listp.Add(new SqlParamete…

程序员如何用“撞针“拯救35亿地球人?
春节假期即将结束,有多少程序员朋友已经离开家乡在返回北上广深等工作所在城市的路上?有多少程序员已经开工大吉开始了新一年的代码征程?回首这一个春节,8 部电影在大年初一齐上线,《流浪地球》在前期预售票房远不如《…
【linux】printf在终端打印彩色hello world
代码 #include <stdio.h>#define NONE "\033[m" #define RED "\033[0;32;31m" #define GREEN "\033[0;32;32m" #define BLUE "\033[0;32;34m" #define YELLOW "\033[1;33m&qu…
看腾讯运维应对“18岁照片全民怀旧”事件的方案,你一定不后悔!
作者丨魏旸:腾讯高级工程师,15年运维经验的老专家,负责QQ空间、微云、QQ空间相册的运维工作,亲历8亿军装照、QQ空间异地多活建设等重大架构升级事件。2017年12月30日,元旦假期的第一天,你的朋友圈被18岁照片…

基于svnserve的SVN服务器(windows下安装与配置)
基于svnserve的SVN服务器(windows下安装与配置)关键字: svn 安装SVNserve 从http://subversion.tigris.org/servlets/ProjectDocumentList?folderID91得到最新版本的Subversion。 如果你已经安装了Subversion,svnserve已经运行,你需要在继续之前把它停…

【c语言】C语言配置文件解析库——iniparser
转载自:http://blog.csdn.net/u011192270/article/details/49339071 C语言配置文件解析库——iniparser前言:在对项目的优化时,发现Linux下没有专门的供给C语言使用的配置文件函数,于是搜索到了iniparser库,可以像那些…