我需要帮助找到一个内核补丁,以从 tty termios API 获取低于 100 毫秒的 VTIME,以减少字符间的间隙。它会阻止读取系统调用,直到 VTIME 超时。
函数 n_tty_read() 是补丁入口点: https://elixir.bootlin.com/linux/latest/source/drivers/tty/n_tty.c#L2131
有人给我建议吗?我必须使用非规范模式(没有帧协议,没有ascii,没有中断)。VMIN 参数为空,因为所有消息长度都是变量。对于多个 uart 系统来说,轮询每个字符的解决方案成本太高,并且隐含多个进程上下文切换。
提取 termios 手册:VTIME 非规范读取的超时(以十分秒为单位)(TIME)。https://man7.org/linux/man-pages/man3/termios.3.html
Linux内核补丁是必要的... HZ除以更大的值是否更好?或者将全局 HZ 设置为较小的值?
Microsoft Windows Serial API 能够配置到 1ms,但 Linux 则不行。所以Windows更适合原始串口处理。 ReadIntervalTimeout:https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddser/ns-ntddser-_serial_timeouts
评论摘录“在非规范模式下......只接受4095个字符”,我认为问题就在这里,也许这就是为什么read_wait队列没有被唤醒。
https://elixir.bootlin.com/linux/latest/source/drivers/tty/n_tty.c#L1667
这样的内核补丁是不明智的,因为它会改变用户空间 API。Linux 努力维护一致的 API,而您要求的补丁可能会破坏现有的应用程序。
即使这样的内核补丁没有改变 API,它也不太可能可靠并实现您未声明的目标。您不能或不应仅依赖 VMIN 和 VTIME 设置来检测时间分隔的消息。
如果 UART 使用 FIFO 来缓冲传入数据,则该硬件缓冲区会掩盖软件可以检测到的字符间距。同样,当 UART 驱动程序使用 DMA 存储接收到的数据时,字符间时序将被掩盖。
termios 处理至少位于 UART 设备驱动程序之上的完整层。termios 层根本看不到与 UART 及其驱动程序处理/缓冲字节后线路上相同的时序信息。
如果您认为 Windows 更适合您的应用程序,那么您应该使用它。但请注意,广告上的内容并不一定是您会得到的。该 Windows API 仅以毫秒精度通告超时规范。这并不意味着您实际上会获得这样的准确性。例如,有这样的警告:
不,你坚持找错地方了。
正如我之前试图向您指出的那样(通过参考这篇文章),可靠的解决方案需要一个计时器来检测空闲的 UART 接收器。然而,即使 UART 硬件实现接收器超时(在我审查的两个 Linux 驱动程序中),该功能也仅用于中止当前/活动的 DMA 操作。
由于接收器超时(可能)检测到时间分隔消息的结束,因此当 UART 驱动程序传递接收到的数据时,需要将此事件/信息传送到 termios 层。
VMIN > 0
这是 termios 需要的原始模式新变体所缺少的信息VTIME > 0
。在这个新变体中,UART 驱动程序需要用接收到的数据指示超时事件,而不是由 termios 检查字符间超时。这不是一个简单的内核补丁。
希望我找到了一些解释,并得出结论,我们面临着API 过时的问题,这意味着可以通过 CPU 过度消耗来绕过。
VTIME 超时粒度历史上被定义为字节间间隙的单位(POSIX 定义的 VTIME=100ms)。当前 Linux 使用的字节间隙仍然对应于110 波特(一百一十)的串行线路。但如今,例如使用 115200 波特率的串行线路,一个字节的 TX 持续时间约为 100 µs(微秒)。
Alan Cox : RE: termios VMIN 和VTIME 行为
POSIX 2007 June §11.1.7 非规范模式输入处理
GNU C 库参考手册,版本 2.37,§17.4.10非规范输入
2005 The SCO Group, Inc. §非规范模式输入处理
为了提出一个保持内核API兼容性的补丁,我认为主要可能有一个分流解决方案:就是使用CANON模式的VEOF参数值(未使用的unsigned char值)来调整VTIME(在应用schedule_timeout函数之前为超时值添加除法因子) ),适用于非CANON模式读取功能。
使用在非佳能模式下未使用的 VEOF 值: https://elixir.bootlin.com/linux/latest/source/include/linux/tty.h#L39
此处应用除法:例如,如果 VEOF 值与默认值不同,则应用减少 VTIME 超时。 https://elixir.bootlin.com/linux/latest/source/drivers/tty/n_tty.c#L2196