我一直在研究terminfo,它在功能字符串中有延迟,例如$<5>
。我试图通过在strace
下运行tput
来了解延迟是如何实现的,即它是通过例如nanosleep
还是通过插入NUL
或其他字符来实现的。这是我试图运行和跟踪的命令:
TERM=ansi77 strace -o log.txt tput dl1
我在ansi77
上选择了dl1
,因为它被定义为dl1=E[M$<5*/>
。然而,我在跟踪中看到的只是写入3个字节:
write(1, "33[M", 3) = 3
- 所以,我的问题是,延迟实际上是如何实施的?填充字符还是简单的进程/线程睡眠
- 我可以在终端模拟器中观察它吗?还是需要真正的硬件终端才能看到它
- 尝试用
tput
复制它有什么缺陷吗
同意@clifffordheath的观点,即填充是通过添加填充字符来完成的,参考可用的文档会有所帮助。
硬件终端并没有停止存在,它们仍然受到ncurses的支持。如果没有填充,这些旧的终端将无法正常工作(丢失或损坏您的输出)。vt100
条目使用填充,而xterm
则不使用填充。
填充字符的terminfo名称为pad
pc
是术语名称(请参阅terminfo(5)):
pad_char pad pc padding char
(instead of null)
terminfo手册页面有一个很长的段落(在能力类型中)处理填充。terminfo格式支持两种类型的填充(咨询和强制性),根据其格式进行区分。termcap只支持后者(当然使用不同的语法),并且与terminfo不同的是,所有延迟都同时发生(这使得"flash"的转义序列通常不起作用)。
命令行tput
程序不仅仅充当函数tputs
的包装器,而是在输出字符串时使用它。命令行程序提供了输出布尔值、数值以及字符串的功能。
库调用tputs
有一个参数,用于计算延迟时考虑的受影响线路的数量(如波特率)。
在OP的问题中
dl1=E[M$<5*/>
指定与受影响的行数成比例的延迟(由"*"
字符标记)。命令行tput
实用程序受影响的行数为1。它调用putp
来执行此操作。然而,它反过来调用delay_output,然后调用baudrate。最后一个函数只有在终端初始化时才初始化。命令行tput
不会初始化终端,因此延迟对不起作用。您应该看到(在适当的速度下)使用库本身的延迟。
ncurses还提供napms
(毫秒)的时间延迟,这与填充不同。
在实现延迟的地方,它是通过传输pad字符来完成的,传统上是NUL字符。可以通过变量pad或pc的termdata/terminfo设置更改pad字符。
填充字符是必要的,因为程序无法知道之前发送的字符何时实际写入,从而启动CPU延迟。即使内核在输出刷新后完成了对字符的处理,字符仍可能在输出设备UART中缓冲。
所需的填充字符数是根据波特率计算的,因此它取决于可用和准确的信息。
库中的tputs例程实现填充(请参见man 3 tputs)。我怀疑命令行工具也会这样做,因为它基本上只是一个包装器。