C-如何在不进行缓冲的情况下轮询()输入? [英] C - how to poll() input without buffering?

查看:70
本文介绍了C-如何在不进行缓冲的情况下轮询()输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检测任何键入为stdin的字符(没有换行符).

I am trying to detect any character typed to stdin (without a newline character).

我尝试过:

setvbuf(stdin, NULL, _IONBF); //This returns 0
struct pollfd pfd = {STDIN_FILENO, POLLIN};

while (!poll(pfd, 1, ms)) {
  /* do some thing, e.g. printf("n\n"); */
}

当我键入 q 时,它似乎并没有停止打印,但是在我按下 enter 后确实停止了打印.我正在使用的系统是arch-linux,编译器是gcc.

It appears not stop printing when I typed q, but did stop after I hit enter. The system I am working on is arch-linux, compiler is gcc.

推荐答案

q 被保留在内核的 TTY层驱动程序/缓冲区中,因为它位于熟"模式.

The q is being held up in the kernel's TTY layer driver/buffer because it is in "cooked" mode.

在此模式下,仅当 driver 看到换行符时,它才会向应用返回一些内容.然后它会返回: q \ n (即 q< newline> ).

In this mode, it will only return something to the app when the driver sees a newline. It then gives back: q\n (i.e. q<newline>).

要使其立即以任何字符返回,必须使用 ioctl 调用将TTY层置于原始"模式.

To have it return immediately on any character, you'll have to use ioctl calls to put the TTY layer into "raw" mode.

您需要使用[建议] termios 调用: tcgetattr tcsetattr

You'll need to use [recommended] the termios calls: tcgetattr and tcsetattr

更新:

单独使用ioctl会起作用吗?哪个命令对应于将终端更改为原始模式?

Will ioctl alone works? Which command is corresponding to change terminal into raw mode?

查看 man termios .它具有有关如何设置原始模式(在手册页中称为非规范"模式)的完整文档.

Look at man termios. It has full documentation for how to set raw mode (what is called "non-canonical" mode in the man page).

距离我这样做已经有一段时间了,但这是一个基本功能.

It's been a while since I've done this, but here's a skeleton function.

尽管该功能会在最后恢复原始状态,但您可能希望在程序启动时将非规范模式设置为一次.

Although the function restores original state at the end, you might want to set non-canonical mode once at program start.

但是,然后,您需要对程序的其他需要常规规范行编辑的部分进行所有自己的行编辑(例如,支持退格键等).

But, then, you'll have to handle all your own line editing (e.g. supporting backspace, etc.) for other sections of your program that want normal canonical line editing.

#include <termios.h>
#include <unistd.h>

void
change_tty(int fd)
{
    struct termios orig;
    struct termios raw;

    // get original cooked/canonical mode values
    tcgetattr(fd,&orig);

    // set options for raw mode
    raw = orig;
#if 0
    raw.c_lflag &= ~ICANON;
    raw.c_cc[VMIN] = ...
    raw.c_cc[VTIME] = ...
#else
    cfmakeraw(&raw);
#endif

    // put unit into raw mode ...
    tcsetattr(fd,TCSANOW,&raw);

    // do stuff in raw mode ...

    // restore original mode
    tcsetattr(fd,TCSANOW,&orig);
}

这篇关于C-如何在不进行缓冲的情况下轮询()输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆