You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下如何设置SSH等非串行tty的波特率?

核心结论
  • SSH会话对应的伪终端(PTY)原生不支持termios接口定义的波特率设置,这是你之前调用cfsetispeed/cfsetospeed、使用stty命令设置波特率完全不生效的根本原因。
  • 波特率本质是物理串行通信硬件的电气层传输速率参数,termios结构里的Bxxx系列常量从设计之初就是给真实串口设备驱动使用的。包括SSH、本地图形终端、telnet在内的所有场景使用的PTY设备,内核驱动中均未实现波特率对应的流控逻辑:你调用相关接口不会返回报错,但驱动层会直接忽略该参数,所有IO操作始终按缓冲区支持的最大速率传输。
符合要求的服务端侧实现方案

所有方案均不需要SSH客户端做任何特殊配置,支持速率动态调整,且排除了逐字符打印加sleep的低效实现。

方案1:内核流量控制层限速(最优,零用户态开销)

直接通过Linux内核自带的流量控制(tc)+ netem模块对当前SSH连接对应的socket做速率限制,所有限速逻辑在内核协议栈完成,无额外用户态开销,不需要修改终端内运行的任何程序。
操作步骤:

  1. 定位当前SSH会话对应的服务端连接信息,执行ss -tnp | grep sshd,匹配你当前客户端IP对应的连接条目,记录服务端使用的临时端口、绑定的网卡名。
  2. 配置根队列规则:
tc qdisc add dev <对应网卡名> root handle 1: prio
  1. 给当前SSH连接的流量绑定独立队列:
tc filter add dev <对应网卡名> parent 1: protocol ip prio 1 u32 match ip sport <SSH服务端临时端口> 0xffff flowid 1:3
  1. 配置目标速率,注意真实串口的波特率对应有效传输速率需要算上帧开销:1200波特对应每字符10位(1起始位+8数据位+1停止位),即有效速率为120Byte/s,示例配置如下:
tc qdisc add dev <对应网卡名> parent 1:3 handle 30: netem rate 120byte
  • 动态调整速率时,直接执行tc qdisc change命令替换速率参数即可,和cfsetospeed的调整逻辑一致,不需要中断现有会话。
  • 如果只需要限制终端输出方向(即从服务端发往客户端的流量),只需要给出站方向配置过滤规则即可,不会影响输入速率。

方案2:优化版PTY中间层方案(兼容低内核版本)

你之前尝试的PTY转发方案开销高,核心问题是采用了逐字符写入加延迟的逻辑,完全可以通过令牌桶限速+块写入的方式把开销降到可忽略的水平:

  • 搭建PTY主从对作为交互终端之后,不要每收到1字节就触发一次write转发,而是按设定的波特率计算时间窗口内的可发送字节数,攒到固定块大小(比如16字节、32字节)之后再批量调用write发送,配合令牌桶算法控制整体速率。
  • 优化后每秒仅需要触发个位数到十位数的write系统调用,相比逐字符发送的方案CPU开销可以降低99%,且传输表现和真实串口完全一致——真实硬件串口本身也是按位传输后批量提交到上层缓冲区,不存在逐字节上报的逻辑。
注意事项
  • 不要浪费时间尝试通过修改termios标志位让原生PTY支持波特率:所有主线内核版本的PTY驱动都没有实现该逻辑,stty查询返回的波特率只是存储在termios结构中的一个无实际作用的数值,不会触发任何流控动作。
  • 逐字符sleep的方案不仅CPU开销高,在有大量突发输出时会出现严重的速率漂移,和真实串口的传输特性差异极大,不建议使用。

内容的提问来源于stack exchange,提问作者InterLinked

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 10:42:20