AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 754975
Accepted
K. PANIK
K. PANIK
Asked: 2023-08-26 19:00:56 +0800 CST2023-08-26 19:00:56 +0800 CST 2023-08-26 19:00:56 +0800 CST

如何修补内核以减少 uart termios API 的 VTIME 间隙?

  • 772

我需要帮助找到一个内核补丁,以从 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 个字符

评论摘录“在非规范模式下......只接受4095个字符”,我认为问题就在这里,也许这就是为什么read_wait队列没有被唤醒。

https://elixir.bootlin.com/linux/latest/source/drivers/tty/n_tty.c#L1667

linux
  • 3 3 个回答
  • 68 Views

3 个回答

  • Voted
  1. sawdust
    2023-08-29T15:46:55+08:002023-08-29T15:46:55+08:00

    我需要帮助找到内核补丁以从 tty termios API 获取低于 100 毫秒的 VTIME,...

    Linux 内核补丁是必要的...

    这样的内核补丁是不明智的,因为它会改变用户空间 API。Linux 努力维护一致的 API,而您要求的补丁可能会破坏现有的应用程序。

    即使这样的内核补丁没有改变 API,它也不太可能可靠并实现您未声明的目标。您不能或不应仅依赖 VMIN 和 VTIME 设置来检测时间分隔的消息。

    如果 UART 使用 FIFO 来缓冲传入数据,则该硬件缓冲区会掩盖软件可以检测到的字符间距。同样,当 UART 驱动程序使用 DMA 存储接收到的数据时,字符间时序将被掩盖。

    termios 处理至少位于 UART 设备驱动程序之上的完整层。termios 层根本看不到与 UART 及其驱动程序处理/缓冲字节后线路上相同的时序信息。


    Microsoft Windows Serial API 能够配置到 1ms,但 Linux 则不行。所以Windows更适合原始串口处理。

    如果您认为 Windows 更适合您的应用程序,那么您应该使用它。但请注意,广告上的内容并不一定是您会得到的。该 Windows API 仅以毫秒精度通告超时规范。这并不意味着您实际上会获得这样的准确性。例如,有这样的警告:

    超时间隔是相对于系统时钟来测量的,超时测量的精度受到系统时钟的粒度的限制。因此,在比指定的超时间隔早一个系统时钟周期和晚一个系统时钟周期之间可能会发生超时,具体取决于系统时钟周期之间该间隔的开始时间和结束时间的准确位置。如果系统时钟中断处理被其他设备的中断处理延迟,超时甚至可能会发生。如果指定的超时间隔接近或小于系统时钟周期之间的周期,则超时可能会立即发生,没有延迟。


    我认为问题就在这里,也许这就是read_wait队列没有被唤醒的原因。

    不,你坚持找错地方了。
    正如我之前试图向您指出的那样(通过参考这篇文章),可靠的解决方案需要一个计时器来检测空闲的 UART 接收器。然而,即使 UART 硬件实现接收器超时(在我审查的两个 Linux 驱动程序中),该功能也仅用于中止当前/活动的 DMA 操作。

    由于接收器超时(可能)检测到时间分隔消息的结束,因此当 UART 驱动程序传递接收到的数据时,需要将此事件/信息传送到 termios 层。VMIN > 0这是 termios 需要的原始模式新变体所缺少的信息VTIME > 0。在这个新变体中,UART 驱动程序需要用接收到的数据指示超时事件,而不是由 termios 检查字符间超时。
    这不是一个简单的内核补丁。

    • 1
  2. K. PANIK
    2023-08-29T06:15:17+08:002023-08-29T06:15:17+08:00

    希望我找到了一些解释,并得出结论,我们面临着API 过时的问题,这意味着可以通过 CPU 过度消耗来绕过。

    VTIME 超时粒度历史上被定义为字节间间隙的单位(POSIX 定义的 VTIME=100ms)。当前 Linux 使用的字节间隙仍然对应于110 波特(一百一十)的串行线路。但如今,例如使用 115200 波特率的串行线路,一个字节的 TX 持续时间约为 100 µs(微秒)。

    Alan Cox : RE: termios VMIN 和VTIME 行为

    它的定义非常明确。它旨在优化块串行操作(uucp 等)

    VMIN - 您期望此数据包的字节数 VTIME - 何时放弃等待

    形式 0,VTIME 也用于对缺少 select/poll 的旧 SYSV 进行轮询

    POSIX 2007 June §11.1.7 非规范模式输入处理

    在非规范模式输入处理中,输入字节不会组装成行,并且不会发生擦除和终止处理。c_cc 数组的 MIN 和 TIME 成员的值用于确定如何处理接收到的字节。POSIX.1-200x 未指定 O_NONBLOCK 的设置是否优先于 MIN 或 TIME 设置。因此,如果设置了 O_NONBLOCK,则无论 MIN 或 TIME 设置如何,read() 都可能立即返回。另外,如果没有可用数据,read() 可能返回 0,或者返回 -1,并将 errno 设置为 [EAGAIN]。MIN 表示 read() 函数成功返回时应接收的最小字节数。TIME是一个0.1秒粒度的定时器,用于突发和短期数据传输的超时。如果 MIN 大于 {MAX_INPUT},则对请求的响应未定义。

    GNU C 库参考手册,版本 2.37,§17.4.10非规范输入

    宏:int VTIME 这是c_cc 数组中TIME 槽的下标。因此,termios.c_cc[VTIME] 就是值本身。

    TIME 槽仅在非规范输入模式下才有意义;指定返回之前等待输入的时间,单位为0.1秒。[...]

    MIN 为零,但 TIME 具有非零值:在这种情况下,读取等待时间 TIME 以使输入可用;单个字节的可用性足以满足读取请求并导致读取返回。当它返回时,它会返回尽可能多的可用字符,最多可达请求的数量。如果在定时器到期之前没有可用的输入,则读取返回零值。

    2005 The SCO Group, Inc. §非规范模式输入处理

    1. (最小值>0,时间>0)。

    因为TIME>0,所以它充当字节间定时器,在接收到第一个数据字节时激活,并在接收到每个字节数据时重置。MIN 和 TIME 相互作用如下:

    • 一旦接收到一个字节的数据,字节间计时器就会启动(请记住,计时器在收到每个字节后都会重置)。
    • 如果在字节间定时器到期之前接收到 MIN 字节的数据,则读取成功完成。
    • 如果字节间计时器在接收到 MIN 字节数据之前到期,则读取操作将传输在此之前接收到的所有字节。

    当 TIME 到期时,读取会传输至少一个字节的数据,因为当且仅当接收到一个字节的数据时,字节间定时器才会启用。使用这种情况的程序必须等待至少一个字节的数据被读取才能继续。如果 (MIN>0, TIME>0),读取会阻塞,直到接收到一个字节的数据激活 MIN 和 TIME,或者信号中断读取。因此,读取传输至少一个字节的数据。

    [...]

    1. (最小值=0,时间>0)。

    由于MIN=0,TIME不再作为字节间定时器,但现在用作处理读取时激活的读取计时器(在佳能中)。一旦接收到任何数据字节或读取计时器到期,读取就会成功完成。如果读取计时器到期,则读取不会传输任何数据字节。如果读取计时器未到期,当且仅当接收到一些数据字节时,读取才会成功完成。如果(MIN=0,TIME>0),读取不会无限期地阻塞等待一个数据字节。如果读取开始后TIME*0.10秒内没有收到字节数据,则返回0表示没有读取到数据。如果在读取开始时缓冲区保存数据,则读取计时器启动,就好像它立即接收到数据一样。当程序可以假设数据在 TIME 间隔后不可用并且可以在数据可用之前完成其他处理时,MIN 和 TIME 非常有用。

    • 0
  3. Best Answer
    K. PANIK
    2023-08-30T17:28:49+08:002023-08-30T17:28:49+08:00

    为了提出一个保持内核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

    • -1

相关问题

  • 有没有办法让 ls 只显示某些目录的隐藏文件?

  • 使用键盘快捷键启动/停止 systemd 服务 [关闭]

  • 需要一些系统调用

  • astyle 不会更改源文件格式

  • 通过标签将根文件系统传递给linux内核

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve