gpt4 book ai didi

c - 当另一个线程正在读取 stdin 时如何在 C 中获取光标位置

转载 作者:行者123 更新时间:2023-11-30 19:03:19 24 4
gpt4 key购买 nike

我正在 Linux (centOS7) 上开发一个控制台 C/C++ 程序,其中一些信息需要显示在终端屏幕的顶部。当主线程处理 stdin 时,另一个线程处理回调并在 stdout 上显示状态。为了避免破坏,回调状态仅显示在屏幕顶部,但光标必须返回到原始位置。

我试过ANSI save/restore cursor但它并不像链接中指出的那样工作。而this stackoverflow solution在单线程中工作,在多线程中不起作用,因为两个线程都会读取 stdin。我尝试了几种方法在获取当前光标位置时暂时禁用标准输入,但它们都失败了:

  • 在 termios.c_cflag 中禁用 CREAD -- tcsetattr() 返回错误(无效参数)
  • tcflow(TCIOFF)
  • dup()

我知道 ncurses 可以工作,但在我的应用程序中,有太多 stdio 函数需要用 ncurses 包装器替换。有谁知道如何保存/恢复光标位置或获取多线程环境中一个线程正在读取 stdin 的当前位置?

最佳答案

I know ncurses would work, but in my app there are too many stdio functions that I need to replace with ncurses wrappers.

所以,你对解决问题不感兴趣,只是想掩盖它。您可以尝试的一种方法是

    flockfile(stdin);
flockfile(stdout);
flockfile(stderr);
/* Write ("\033[6n") to standard input,
and read the ("\033[" row ";" column "R") response */
funlockfile(stderr);
funlockfile(stdout);
funlockfile(stdin);

参见man 3 flockfile()了解详情。这个想法是获取所有三个标准流的 C 库内部锁,以便在它们上执行 I/O 的任何其他线程都将阻塞,直到我们在该流上调用 funlockfile()

这不会以任何方式影响 STDIN_FILENO、STDOUT_FILENO 或 STDERR_FILENO 的低级 I/O。

<小时/>

rici 的一条评论让我意识到实际上有一种方法不需要重写原始代码。

使用辅助进程(或线程)来处理标准输入、标准输出、标准错误和终端的所有 I/O。

本质上,在程序的一开始,您构建了三个管道和一个 Unix 域数据报套接字对,并创建了帮助程序。

(如果您使用辅助进程,您可以将其制作为外部可执行文件,并使用 ncurses 编写它,而不会影响父程序。)

帮助程序通过管道和套接字对连接到父进程。父级将 STDIN_FILENOSTDOUT_FILENOSTDERR_FILENO 描述符替换为管道末端(关闭它们各自的原始描述符)。这样,它只能从助手中读取数据并写入助手,而不能直接写入原始流。

Unix 域数据报套接字对允许父级从帮助器查询当前光标位置(并且可能执行其他类似操作)。

帮助器从两个父管道和原始标准输入中读取,并写入父管道之一和原始标准输出和错误。我个人会将辅助管道末端设置为非阻塞,并使用 select(),因此单线程辅助程序就足够了。

关于c - 当另一个线程正在读取 stdin 时如何在 C 中获取光标位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54165575/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com