关于 getchar() 循环如何在内部工作的困惑 [英] Confusion about how a getchar() loop works internally

查看:16
本文介绍了关于 getchar() 循环如何在内部工作的困惑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在下面包含了一个使用 getchar() 的示例程序,以供参考(不是任何人都可能需要它),如果您愿意,可以随时解决有关它的问题.但我的问题是:

I've included an example program using getchar() below, for reference (not that anyone probably needs it), and feel free to address concerns with it if you desire. But my question is:

当程序调用getchar()时到底发生了什么?

What exactly is going on when the program calls getchar()?

这是我的理解(请澄清或更正我):

Here is my understanding (please clarify or correct me):

  1. 调用 getchar 时,它会检查 STDIN 缓冲区以查看是否有任何输入.
  2. 如果没有任何输入,getchar 就会休眠.
  3. 唤醒后,getchar 会检查是否有任何输入,如果没有,则使其再次进入睡眠状态.
  4. 重复第 2 步和第 3 步,直到有输入为止.
  5. 一旦有输入(按照惯例,末尾包含一个EOF"),getchar 将返回此输入的第一个字符并执行某事 以指示对 getchar 的下一次调用应返回来自同一个缓冲区的第二个字母?我不太确定那是什么.
  6. 当除 EOF 外没有其他字符时,getchar 是否刷新缓冲区?
  1. When getchar is called, it checks the STDIN buffer to see if there is any input.
  2. If there isn't any input, getchar sleeps.
  3. Upon wake, getchar checks to see if there is any input, and if not, puts it self to sleep again.
  4. Steps 2 and 3 repeat until there is input.
  5. Once there is input (which by convention includes an 'EOF' at the end), getchar returns the first character of this input and does something to indicate that the next call to getchar should return the second letter from the same buffer? I'm not really sure what that is.
  6. When there are no more characters left other than EOF, does getchar flush the buffer?

我使用的术语可能不太正确.

The terms I used are probably not quite correct.

#include <stdio.h>

int getLine(char buffer[], int maxChars);

#define MAX_LINE_LENGTH 80

int main(void){

    char line[MAX_LINE_LENGTH];
    int errorCode;

    errorCode = getLine(line, sizeof(line));
    if(errorCode == 1)
        printf("Input exceeded maximum line length of %d characters.
", MAX_LINE_LENGTH);
    printf("%s
", line);

    return 0;

}

int getLine(char buffer[], int maxChars){
    int c, i = 0;
    while((c = getchar()) != EOF && c != '
' && i < maxChars - 1)
        buffer[i++] = c;
    buffer[i++] = '';
    if(i == maxChars)
        return 1;
    else
        return 0;
}

推荐答案

第 2-4 步略有偏差.

Step 2-4 are slightly off.

如果标准 I/O 缓冲区中没有输入,getchar() 调用函数重新加载缓冲区.在类 Unix 系统上,通常最终调用 read() 系统调用,并且 read() 系统调用使进程进入睡眠状态,直到有输入被处理,或者内核知道将没有要处理的输入(EOF).当读取返回时,代码会调整数据结构,以便 getchar() 知道有多少数据可用.您的描述暗示了轮询;标准 I/O 系统不轮询输入.

If there is no input in the standard I/O buffer, getchar() calls a function to reload the buffer. On a Unix-like system, that normally ends up calling the read() system call, and the read() system call puts the process to sleep until there is input to be processed, or the kernel knows there will be no input to be processed (EOF). When the read returns, the code adjusts the data structures so that getchar() knows how much data is available. You description implies polling; the standard I/O system does not poll for input.

步骤 5 使用调整后的指针返回正确的值.

Step 5 uses the adjusted pointers to return the correct values.

真的没有 EOF 字符;它是一个状态,而不是一个字符.即使您键入 Control-DControl-Z 来指示EOF",该字符也不会插入到输入流中.事实上,这些字符会导致系统刷新任何仍在等待行编辑"操作(如退格)来更改它们的键入字符,以便它们可用于 read() 系统调用.如果没有这样的字符,则 read() 返回 0 作为可用字符数,即 EOF.然后 getchar() 返回值 EOF(通常是 -1 但保证为负,而有效字符保证为非负(零或正)))

There really isn't an EOF character; it is a state, not a character. Even though you type Control-D or Control-Z to indicate 'EOF', that character is not inserted into the input stream. In fact, those characters cause the system to flush any typed characters that are still waiting for 'line editing' operations (like backspace) to change them so that they are made available to the read() system call. If there are no such characters, then read() returns 0 as the number of available characters, which means EOF. Then getchar() returns the value EOF (usually -1 but guaranteed to be negative whereas valid characters are guaranteed to be non-negative (zero or positive)).

所以基本上,而不是轮询,是不是点击Return会导致某个I/O中断,然后当操作系统收到这个中断时,它会唤醒任何为I/O而休眠的进程?

So basically, rather than polling, is it that hitting Return causes a certain I/O interrupt, and then when the OS receives this, it wakes up any processes that are sleeping for I/O?

是的,点击Return 会触发中断,操作系统内核会处理它们并唤醒正在等待数据的进程.终端驱动程序在中断发生时被内核唤醒,并决定如何处理刚刚接收到的字符.它们可能会被藏起来以供进一步处理(规范模式)或立即可用(原始模式)等.当然,假设输入是终端;如果输入来自磁盘文件,则在很多方面都更简单——或者如果它是管道,或者……

Yes, hitting Return triggers interrupts and the OS kernel processes them and wakes up processes that are waiting for the data. The terminal driver is woken by the kernel when interrupt occurs, and decides what to do with the character(s) that were just received. They may be stashed for further processing (canonical mode) or made available immediately (raw mode), etc. Assuming, of course, that the input is a terminal; if the input is from a disk file, it is simpler in many ways — or if it is a pipe, or …

名义上,不是终端应用程序被中断唤醒;是内核首先唤醒,然后在终端应用程序中运行的 shell 被唤醒,因为有数据可供它读取,只有当有输出时,终端应用程序才会被唤醒.

Nominally, it isn't the terminal app that gets woken by the interrupt; it is the kernel that wakes first, then the shell running in the terminal app that is woken because there's data for it to read, and only when there's output does the terminal app get woken.

我说名义上"是因为实际上终端应用程序确实通过 pty(伪 tty)来调解 I/O,但我认为它发生在内核级别并且终端应用程序相当参与在这个过程的后期.您输入的键盘与您输入的内容出现的显示器之间确实存在巨大的脱节.

I say 'nominally' because there's an outside chance that in fact the terminal app does mediate the I/O via a pty (pseudo-tty), but I think it happens at the kernel level and the terminal application is involved fairly late in the process. There's a huge disconnect really between the keyboard where you type and the display where what you type appears.

另见规范与非规范终端输入.

这篇关于关于 getchar() 循环如何在内部工作的困惑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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