Linux 阻塞与非阻塞串行读取

2024-09-30 15:23:00
admin
原创
282
摘要:问题描述:我有这个用于在 Linux 中从串行读取的代码,但我不知道在读取串行端口时阻塞和非阻塞之间有什么区别,以及在哪种情况下哪一个更好?解决方案 1:在我看来,您提到的代码编码和注释都很糟糕。该代码不符合 POSIX 可移植性实践,如正确设置终端模式和POSIX 操作系统串行编程指南中所述。该代码没有提到...

问题描述:

我有这个用于在 Linux 中从串行读取的代码,但我不知道在读取串行端口时阻塞和非阻塞之间有什么区别,以及在哪种情况下哪一个更好?


解决方案 1:

在我看来,您提到的代码编码和注释都很糟糕。该代码不符合 POSIX 可移植性实践,如正确设置终端模式POSIX 操作系统串行编程指南中所述。该代码没有提到它使用非规范(又称原始)模式,并重用“阻塞”和“非阻塞”术语来描述VMINVTIME属性。

(该代码的作者报告说它早于 POSIX 标准,因此不符合要求。这是可以理解的,但随后发布并提倡使用可能不可移植的旧代码(即在其他情况下无法按预期运行)是值得怀疑的。)


“阻塞”与“非阻塞”读取的传统定义基于读取调用“何时”返回到您的程序(并使用下一个语句恢复执行)以及程序的读取缓冲区中是否会存储数据。阻塞读取是默认模式,除非通过使用 O_NONBLOCK 或 O_NDELAY 标志打开串行终端来请求非阻塞。

规范模式

对于串行终端的阻塞规范读取调用,一行(又称记录)文本将始终返回到提供的缓冲区中(除非发生错误)。读取调用将阻塞(即暂停执行程序),直到收到并处理行终止符为止。

串行终端的非阻塞标准读取调用将始终“立即”返回。读取可能会或可能不会返回任何数据。

如果(自上次读取调用以来)至少已收到一行文本并将其存储在系统缓冲区中,则将从系统缓冲区中删除最旧的行并将其复制到程序的缓冲区中。返回代码将指示数据长度。如果

(自上次读取调用以来)尚未收到和处理行终止符,则没有可用的(完整)文本行。read ()将返回 EAGAIN 错误(即 -1 返回代码和errno设置为 EAGAIN)。然后,您的程序可以执行一些计算,或从另一个设备请求 I/O,或者延迟/休眠。在任意延迟后或通过poll()select()通知,您的程序可以重试read()

该答案中包含一个使用阻塞规范模式进行读取的示例程序。

非规范模式

当串行终端配置为非规范模式时,应使用termios c_cc数组元素VMINVTIME
来控制“阻塞”,但这要求终端以默认阻塞模式打开,即不指定 O_NONBLOCK 打开标志。
否则 O_NONBLOCK 将优先于 VMIN 和 VTIME 规范,并且read()会将errno设置为 EAGAIN 并在没有可用数据时立即返回 -1 而不是 0。(这是在最近的 Linux 3.x 内核中观察到的行为;较旧的 2.6.x 内核可能表现不同。)

termios 手册页将 ( c_cc数组索引) VMIN描述为“非规范读取的最小字符数”,将 ( c_cc数组索引) VTIME描述为“非规范读取的超时时间(以十分之一秒为单位)”。程序应调整

VMIN以适应预期的典型消息或数据报长度和/或每次读取 ()检索和处理的数据的最小大小。程序应调整

VTIME以适应预期的典型串行数据突发性或到达率和/或等待数据或基准的最大时间。

VMIN和VTIME值相互作用以确定read 应何时返回的标准;它们的确切含义取决于其中哪些是非零的。有四种可能的情况。此网页对此进行了解释:

  • VMIN = 0 且 VTIME = 0

这是一个完全非阻塞的读取 - 调用会立即从驱动程序的输入队列直接得到满足。如果有数据,则将其传输到调用者的缓冲区(最多 n 个字节)并返回。否则会立即返回零以表示“无数据”。我们会注意到,这是串行端口的“轮询”,这几乎总是一个坏主意。如果反复执行,它会消耗大量的处理器时间并且效率极低。除非您真的非常清楚自己在做什么,否则不要使用此模式。

  • VMIN = 0 且 VTIME > 0

这是一个纯定时读取。如果输入队列中有数据,则将数据传输到调用者的缓冲区(最多 n 个字节),并立即返回给调用者。否则,驱动程序将阻塞,直到数据到达,或者从调用开始到 VTIME 十分之一到期。如果计时器到期而没有数据,则返回零。单个字节足以满足此读取调用,但如果输入队列中有更多可用数据,则将其返回给调用者。请注意,这是一个整体计时器,而不是字符间计时器。

[警告:VMIN = 0 且 VTIME > 0 是超时读取,而不是定时读取。此读取不会等待VTIME 持续时间然后返回可用内容。只有在没有可用字符时才会发生超时。否则,只要有字符可用,读取就会立即返回。]

  • VMIN > 0 且 VTIME > 0

当 VMIN 个字符已传输到调用者的缓冲区,或者 VTIME 在字符之间十分之一到期时,read() 得到满足。由于此计时器直到第一个字符到达才启动,因此如果串行线路空闲,此调用可能会无限期阻塞。这是最常见的操作模式,我们认为 VTIME 是字符间超时,而不是整体超时。此调用绝不会返回零字节读取。

  • VMIN > 0 且 VTIME = 0

这是一个计数读取,只有当至少 VMIN 个字符已传输到调用者的缓冲区时才会满足 - 不涉及计时组件。此读取可以从驱动程序的输入队列(调用可以立即返回)中满足,或者通过等待新数据到达来满足:在这方面,调用可能会无限期阻塞。我们认为,如果 nbytes 小于 VMIN,则这是未定义的行为。

请注意,当 VMIN=1 时,VTIME 规范将变得无关紧要。任何数据的可用性始终满足单个字节的最小标准,因此可以忽略时间标准(因为它将是具有非零 VMIN 的字符间时间规范)。@IanAbbot 指出了这种特殊情况。


您提到的代码将“非阻塞”模式配置为 VMIN=0 和 VTIME=5。这并不总是会导致 read() 像非阻塞规范读取那样立即返回;使用该代码,read() 可以等待至少半秒钟才返回。

“非阻塞”的传统定义是您的调用程序在系统调用期间不会被抢占,并且(几乎)立即获得控制权。

要获得(无条件和)立即返回(对于非规范读取),请设置 VMIN=0 和 VTIME=0(并伴有警告)。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用