【问题标题】:Why don't termcaps work before a `write` syscall?为什么 termcaps 在 `write` 系统调用之前不起作用?
【发布时间】:2021-01-13 15:56:10
【问题描述】:

为什么这个程序的输出没有下划线

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  write(1, "Hello world!\n", 13);
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

但这是?

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  puts("Hello world!");
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

编辑

问题确实与缓冲区管理有关!如果我添加fflush,则字符串会正确加下划线

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  fflush(stdout);
  write(1, "Hello world!\n", 13);
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

【问题讨论】:

  • 因为 termcap/terminfo 假定它完全控制了显示,而 write() 颠覆了这一点。您必须refresh() 才能获得放置的 termcap/terminfo 信息。那么如果你幸运的话,write() 可能会起作用。但是您不应该将 termcap/terminfo 函数与低级 write()(或 read())函数混合使用。
  • @JonathanLeffler 谢谢!但是write() 与putchar() 和puts() 等“高级”函数有何不同?除了缓冲区管理?
  • 嗯……我很想说“这都是关于缓冲区管理的”,但这是假设curses 而不仅仅是termcap 或terminfo。然后我做了噩梦......然后我查看了手册页(Mac 上的man 3 tputs),它们毕竟是curses 的一部分——因此很可能它是都是关于缓冲区管理的。您没有展示 MCVE(Minimal, Complete, Verifiable Example — 或 MRE 或 SO 现在使用的任何名称)或 SSCCE(Short, Self-Contained, Correct Example)。程序中还有什么?
  • 问题确实与缓冲区管理有关!感谢您的帮助:)
  • The issue is, indeed 请将其发布为您问题的答案。

标签: c unix terminal termcap


【解决方案1】:

产生差异的原因是putchar 和puts 被缓冲,而write 没有。在这个例子中

int main() {
  tgetent(NULL, getenv("TERM"));
  tputs(tgetstr("us", NULL), 1, &putchar);
  write(1, "Hello world!\n", 13);
  tputs(tgetstr("ue", NULL), 1, &putchar);
}

作者写的字

write(1, "Hello world!\n", 13);

可能首先到达屏幕,因为(与tputs 调用不同)它们是立即写入的。 tputs 调用写入的字符存储在缓冲区中(通常比从 tgetstr 返回的字符串大很多),并且由于您没有提供其他方法来刷新缓冲区,所以那些由运行时的清理在它退出时写入。

如果没有显式的 return 语句,C 标准保证它与调用 exit 具有相同的效果(对每个打开的文件执行 fflush,包括 stdout 等流)。

虽然您原则上可以构造一个包含极长字符串的 termcap,但 termcap 描述应该限制为 1023 个字节(甚至 terminfo 描述通常限制为 4096 个字节),而标准 I/O 缓冲区大小通常是是该限制的几倍,因此如果没有大量工作(即更改运行时...),您将不会看到那些tputs 调用。

【讨论】:

    猜你喜欢
    • 2017-09-12
    • 1970-01-01
    • 2012-01-24
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 2015-05-03
    相关资源
    最近更新 更多