读取标准模式下的标准输出从无缓冲更改为行缓冲 [英] read changes stdout from unbuffered to line buffered in canonical mode

查看:206
本文介绍了读取标准模式下的标准输出从无缓冲更改为行缓冲的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在规范模式下使用这段代码时:

When I use this piece of code in canonical mode:

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

static struct termios newt;
static struct termios oldt;

static void kb_fini(void)
{
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
}

void kb_init(void)
{
    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    newt.c_lflag &= (tcflag_t)~(ICANON | ECHO | ISIG);
    newt.c_cc[VMIN] = 1;
    newt.c_cc[VTIME] = 0;
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    atexit(kb_fini);
}

int main(void)
{
    int c;

    kb_init();
    printf("Press q ");
    c = getchar();
    if (c == 'q') {
        printf("q was pressed\n");
    }
    return 0;
}

在按下q

切换到read:

int main(void)
{
    char c;

    kb_init();
    printf("Press q ");
    read(STDIN_FILENO, &c, 1);
    if (c == 'q') {
        printf("q was pressed\n");
    }
    return 0;
}

在按下q之前,不会显示"Press q".

Doesn't show "Press q " until q is pressed.

这是为什么?

推荐答案

正如我在

As I observed in a comment, the standard I/O package knows what is happening and coordinates things so that the pending output to standard output (stdout) is flushed before invoking the read operation on standard input (stdin) — at least when the output and input are an 'interactive device', aka terminal. Note that the synchronization is not actually mandated by the C standard, but most implementations provide it.

read()系统调用不知道或不在乎标准I/O包的情况.它无权访问任何文件流,也无权访问这些流专用的任何数据(例如缓冲输出).因此,它无法确保在尝试读取输入之前刷新挂起的标准输出.

The read() system call doesn't know or care about what's going on with the standard I/O package. It has no access to any of the file streams, nor to any of the data private to those streams (such as buffered output). Therefore, it cannot ensure that pending standard output is flushed before it attempts to read the input.

如果要混合使用两种模式,请在使用read()之前确保使用fflush(stdout);fflush(0);.

If you're going to mix the two modes, make sure you fflush(stdout); or fflush(0); before using read().

混合使用两种模式是否具有明确的行为?

Does mixing the two modes have well defined behaviour?

这取决于您如何混合它们.如果将stdout用作输出,将STDIN_FILENO用作输入,那么除了默认情况下缺少同步之外,没有任何问题.如果您尝试将stdout操作与直接在STDOUT_FILENO上的操作混合在一起,或者将stdin操作与直接在STDIN_FILENO上的操作混合使用,则通常会遭受很多伤害.当您珍惜自己(或用户)的理智时,请不要尝试这样做.除其他问题外,标准I/O库可能会提前缓冲,并且文件描述符函数将无法查看已经读取的标准I/O.相反,在编写时,标准I/O库将缓冲,而文件描述符I/O将不缓冲.

It depends on how you mix them. If you use stdout for output and STDIN_FILENO for input, there's no problem beyond the lack of synchronization by default. If you try to mix stdout operations with operations directly on STDOUT_FILENO, or stdin operations with operations directly on STDIN_FILENO, then you are in for a world of hurt, in general. Don't try that as you value your own (or your users') sanity. Amongst other problems, the standard I/O library can buffer ahead and the file descriptor functions won't be able to see what standard I/O already read. Conversely, on writing, the standard I/O library will buffer and the file descriptor I/O won't.

这篇关于读取标准模式下的标准输出从无缓冲更改为行缓冲的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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