简体   繁体   English

非阻塞stdio

[英]Non-blocking stdio

I'm working on a program which will be taking in user input from the console as well as printfing out in a separate thread. 我正在开发一个程序,它将从控制台接收用户输入以及在单独的线程中打印出来。 I want to avoid situations where the user is halfway through typing something in and a printf comes along and prints itself at the cursor. 我想避免用户在输入内容的中途并且printf出现并在光标处打印自己的情况。

Is there a way to do non-blocking io in c from the console window? 有没有办法在控制台窗口中执行c中的非阻塞io? Ideally, capturing keypresses or something like that such that what the user types doesn't appear on the screen. 理想情况下,捕获按键或类似的东西,使得用户键入的内容不会出现在屏幕上。 I'm developing in Ubuntu, and it's best if I don't have to use things like ncurses. 我正在开发Ubuntu,如果我不必使用像ncurses这样的东西,那就最好了。

using termios you can disable terminal echoing: 使用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 */
}

then before exit (use atexit ) you must restore the terminal: 然后在退出之前(使用atexit )你必须恢复终端:

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

Here's an example of how to turn off echo from C, taken directly from an HP forum (and I haven't personally tested it): 这是一个如何从C关闭回声的示例,直接来自HP论坛 (我还没有亲自测试过):

Okay this should be a simple example of turning off echo: 好的,这应该是一个关闭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); } 

NOTE: It is very important that you have signal handlers to catch SIGINT, SIGTERM, ... and reset the terminal using the original termios because the last tcsetattr() wins and this applies to the terminal device NOT simply the process. 注意:让信号处理程序捕获SIGINT,SIGTERM,并使用原始termios重置终端是非常重要的,因为最后一个tcsetattr()获胜,这适用于终端设备而不仅仅是进程。 If you leave the process with echo off, it will be off in the shell as well. 如果你将回显关闭,那么它也将在shell中关闭。

Otherwise, if Bash is a suitable approach, apparently you can just do stty -echo . 否则,如果Bash是一个合适的方法,显然你可以做stty -echo

Turning off echo or using non-blocking I/O isn't the answer, if I understand your question correctly. 如果我正确理解您的问题,关闭回声或使用非阻塞I / O不是答案。 Rather, you want to prevent a background thread from interrupting a user input thread, right? 相反,你想防止后台线程中断用户输入线程,对吧?

For that, you'll need access to raw keypresses instead of line-buffered input. 为此,您需要访问原始按键而不是行缓冲输入。 I don't know why you're allergic to ncurses or similar libraries; 我不知道你为什么对ncurses或类似的图书馆过敏; that's what they're for! 这就是他们的目的! I guess you could do it with termios or ioctl calls, if that's how you roll.... 我想你可以用termios或ioctl调用来做,如果这就是你如何滚动....

But to solve your multi-threaded TTY output problem, you could do this: 但要解决多线程TTY输出问题,您可以这样做:

1) Create a mutex to control who can access the console 1)创建一个互斥锁来控制谁可以访问控制台

In the background thread , to output a message: 在后台线程中 ,输出一条消息:

Grab the mutex; 抓住互斥体; write the message; 写信息; release the mutex; 释放互斥锁; go back to sleep! 回去睡觉!

In the user input thread: 在用户输入线程中:

Grab the mutex when new input is detected. 检测到新输入时抓取互斥锁。 Keep exclusive access until the user hits enter, then release the mutex and give the background thread a chance to talk. 在用户点击进入之前保持独占访问权限,然后释放互斥锁并为后台主题提供通话机会。

Does that help? 这有帮助吗?

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

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