jjzjj

linux - termios VMIN VTIME 和阻塞/非阻塞读取操作

coder 2023-06-20 原文

我正在尝试为 Linux 编写一个简单的 C 串行通信程序。我对阻塞/非阻塞读取和 VMIN/VTIME 关系感到困惑。

我的问题是,是否应该根据我是否有阻塞/非阻塞打开调用来设置 VMIN/VTIME?

例如,如果我有以下公开电话:

open( "/dev/ttyS0", O_RDWR|O_NONBLOCK|O_NOCTTY)

我应该将 VMIN/VTIME 设置为:

.c_cc[VTIME]    = 0;    
.c_cc[VMIN]     = 0;

如果我有这样的阻塞模式:

open( "/dev/ttyS0", O_RDWR|O_NOCTTY)

我应该将 VMIN/VTIME 设置为:

.c_cc[VTIME]    = 0;    
.c_cc[VMIN]     = 1;

?

即使正确设置了端口打开标志,设置 VMIN/VTIME 有什么区别吗?

如果有人能帮助我理解 VMIN/VTIME 和阻塞/非阻塞端口之间的关系,我将不胜感激。

谢谢

最佳答案

安德烈是对的。在非阻塞模式下,VMIN/VTIME 无效(FNDELAY/O_NDELAY 似乎是 O_NONBLOCK 的 linux 变体,可移植的 POSIX 标志)。

当在非阻塞模式下对文件使用 select() 时,您会为到达的每个字节获得一个事件。在高串行数据速率下,这会重击 CPU。 VMIN 最好使用阻塞模式,这样 select() 在触发事件之前等待一个数据 block ,而 VTIME 用于限制延迟,对于小于 VMIN 的 block 。

Sam 说“如果您想确保每半秒获取一次数据,您可以设置 vtime”(VTIME = 5)。

凭直觉,您可能认为这是真的,但事实并非如此。 BSD termios 手册页对它的解释比 linux 更好(尽管它们的工作方式相同)。 VTIME 计时器是一个字节间 计时器。它从到达串行端口的每个新字节开始。在最坏的情况下,select() 最多可以等待 20 秒才能触发事件。

假设您有 VMIN = 250,VTIME = 1,串行端口为 115200 bps。还假设您有一个附加设备以 9 cps 的一致速率缓慢发送单个字节。字节之间的时间是 0.11 秒,足够让 0.10 的字节间计时器超时,并且 select() 为每个字节报告一个可读事件。一切顺利。

现在假设您的设备将其输出速率提高到 11 cps。字节之间的时间是 0.09 秒。字节间计时器到期的时间还不够长,并且每个新字节都会重新开始。要获得可读事件,必须满足 VMIN = 250。在 11 cps 下,这需要 22.7 秒。您的设备似乎已停滞,但 VTIME 设计才是延迟的真正原因。

我用两个 Perl 脚本、发送器和接收器、一个双端口串口卡和一根零调制解调器电缆对此进行了测试。我证明它像手册页所说的那样工作。 VTIME 是一个字节间计时器,随着每个新字节的到来而重置。

更好的设计是让计时器固定,而不是滚动。它会继续滴答直到它到期,或者 VMIN 被满足,以先到者为准。现有设计可以修复,但需要克服 30 年的遗留问题。

在实践中,你可能很少遇到这样的场景。但它潜伏着,所以要小心。

关于linux - termios VMIN VTIME 和阻塞/非阻塞读取操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20154157/

有关linux - termios VMIN VTIME 和阻塞/非阻塞读取操作的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  3. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  4. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  5. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  6. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  7. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  8. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  9. ruby - 是否可以在不实际发送或读取数据的情况下查明 ruby​​ 套接字是否处于 ESTABLISHED 或 CLOSE_WAIT 状态? - 2

    s=Socket.new(Socket::AF_INET,Socket::SOCK_STREAM,0)s.connect(Socket.pack_sockaddr_in('port','hostname'))ssl=OpenSSL::SSL::SSLSocket.new(s,sslcert)ssl.connect从这里开始,如果ssl连接和底层套接字仍然是ESTABLISHED,或者它是否在默认值7200之后进入CLOSE_WAIT,我想检查一个线程几秒钟甚至更糟的是在实际上不需要.write()或.read()的情况下关闭。是用select()、IO.select()还是其他方法完成

  10. ruby - 在 Ruby 中是否有一种惯用的方法来操作 2 个数组? - 2

    a=[3,4,7,8,3]b=[5,3,6,8,3]假设数组长度相同,是否有办法使用each或其他一些惯用方法从两个数组的每个元素中获取结果?不使用计数器?例如获取每个元素的乘积:[15,12,42,64,9](0..a.count-1).eachdo|i|太丑了...ruby1.9.3 最佳答案 使用Array.zip怎么样?:>>a=[3,4,7,8,3]=>[3,4,7,8,3]>>b=[5,3,6,8,3]=>[5,3,6,8,3]>>c=[]=>[]>>a.zip(b)do|i,j|c[[3,5],[4,3],[7,6],

随机推荐