繁体   English   中英

非阻塞stdio

[英]Non-blocking stdio

我正在开发一个程序,它将从控制台接收用户输入以及在单独的线程中打印出来。 我想避免用户在输入内容的中途并且printf出现并在光标处打印自己的情况。

有没有办法在控制台窗口中执行c中的非阻塞io? 理想情况下,捕获按键或类似的东西,使得用户键入的内容不会出现在屏幕上。 我正在开发Ubuntu,如果我不必使用像ncurses这样的东西,那就最好了。

使用termios可以禁用终端回显:

#include <termios.h>

struct termios oflags, nflags;
tcgetattr(fileno(stdin), &oflags);
nflags = oflags;
nflags.c_lflag &= ~ECHO;
nflags.c_lflag |= ECHONL;

if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) {
    /* handle error */
}

然后在退出之前(使用atexit )你必须恢复终端:

if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
    /* handle error */
}

这是一个如何从C关闭回声的示例,直接来自HP论坛 (我还没有亲自测试过):

好的,这应该是一个关闭echo的简单例子:

 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <termios.h> #define STDIN_FDES 0 struct termios save; int main(int argc, char *argv[]) { int cc = 0; char s_tmp[80],*p = NULL; struct termios work; cc = tcgetattr(STDIN_FDES,&save); work = save; work.c_lflag &= ~(ECHO); cc = tcsetattr(STDIN_FDES,TCSANOW,&work); (void) printf("\\nEnter value: "); (void) fflush(stdout); p = fgets(s_tmp,sizeof(s_tmp),stdin); if (p != NULL) (void) printf("Out -> %s\\n",p); cc = tcsetattr(STDIN_FDES,TCSANOW,&save); return(cc); } 

注意:让信号处理程序捕获SIGINT,SIGTERM,并使用原始termios重置终端是非常重要的,因为最后一个tcsetattr()获胜,这适用于终端设备而不仅仅是进程。 如果你将回显关闭,那么它也将在shell中关闭。

否则,如果Bash是一个合适的方法,显然你可以做stty -echo

如果我正确理解您的问题,关闭回声或使用非阻塞I / O不是答案。 相反,你想防止后台线程中断用户输入线程,对吧?

为此,您需要访问原始按键而不是行缓冲输入。 我不知道你为什么对ncurses或类似的图书馆过敏; 这就是他们的目的! 我想你可以用termios或ioctl调用来做,如果这就是你如何滚动....

但要解决多线程TTY输出问题,您可以这样做:

1)创建一个互斥锁来控制谁可以访问控制台

在后台线程中 ,输出一条消息:

抓住互斥体; 写信息; 释放互斥锁; 回去睡觉!

在用户输入线程中:

检测到新输入时抓取互斥锁。 在用户点击进入之前保持独占访问权限,然后释放互斥锁并为后台主题提供通话机会。

这有帮助吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM