关于getchar()循环如何在内部工作的混淆

关于getchar()循环如何在内部工作的混淆,c,io,internals,getchar,C,Io,Internals,Getchar,我在下面提供了一个使用getchar()的示例程序,供参考(不是任何人都可能需要它),如果您愿意,可以随意解决它的问题。但我的问题是: 当程序调用getchar()时,到底发生了什么 以下是我的理解(请澄清或纠正我): 调用getchar时,它会检查STDIN缓冲区以查看是否有任何输入 如果没有任何输入,getchar将休眠 唤醒后,getchar检查是否有任何输入,如果没有,则将其自身再次置于睡眠状态 重复步骤2和3,直到有输入 一旦有了输入(按照惯例,它的末尾包含一个“EOF”),getch

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

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

以下是我的理解(请澄清或纠正我):

  • 调用getchar时,它会检查STDIN缓冲区以查看是否有任何输入
  • 如果没有任何输入,getchar将休眠
  • 唤醒后,getchar检查是否有任何输入,如果没有,则将其自身再次置于睡眠状态
  • 重复步骤2和3,直到有输入
  • 一旦有了输入(按照惯例,它的末尾包含一个“EOF”),getchar将返回该输入的第一个字符,并指示下一次调用getchar时应该从同一缓冲区返回第二个字母?我不确定那是什么
  • 当除EOF之外没有其他字符时,getchar是否会刷新缓冲区
  • 我使用的术语可能不太正确

    #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.\n", MAX_LINE_LENGTH);
        printf("%s\n", line);
    
        return 0;
    
    }
    
    int getLine(char buffer[], int maxChars){
        int c, i = 0;
        while((c = getchar()) != EOF && c != '\n' && i < maxChars - 1)
            buffer[i++] = c;
        buffer[i++] = '\0';
        if(i == maxChars)
            return 1;
        else
            return 0;
    }
    
    #包括
    int getLine(字符缓冲区[],int maxChars);
    #定义最大直线长度80
    内部主(空){
    字符行[最大行长度];
    国际误码;
    errorCode=getLine(line,sizeof(line));
    如果(错误代码==1)
    printf(“输入超过了%d个字符的最大行长。\n”,最大行长);
    printf(“%s\n”,第行);
    返回0;
    }
    int getLine(字符缓冲区[],int maxChars){
    int c,i=0;
    while((c=getchar())!=EOF&&c!='\n'&&i
    步骤2-4稍微有点不正确

    如果标准I/O缓冲区中没有输入,
    getchar()
    调用函数重新加载缓冲区。在类Unix的系统上,它通常会调用
    read()
    系统调用,而
    read()
    系统调用会将进程置于休眠状态,直到有输入要处理,或者内核知道没有输入要处理(EOF)。当读取返回时,代码会调整数据结构,以便
    getchar()
    知道有多少数据可用。你的描述意味着投票;标准I/O系统不轮询输入

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

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

    因此,基本上,不是轮询,而是点击Return会导致某个I/O中断,然后当操作系统接收到该中断时,它会唤醒任何正在休眠I/O的进程吗

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

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

    我之所以说“名义上”,是因为实际上终端应用程序确实有可能通过pty(伪tty)调解I/O,但我认为它发生在内核级别,并且终端应用程序在这个过程中涉及的时间相当晚。在你输入的键盘和你输入的内容出现的显示器之间存在着巨大的差异


    另请参见。

    您将继续调用
    getchar
    ,直到它返回EOF。在这一点上,它是输入的结束,所以缓冲区中不应该有任何剩余的东西需要刷新。字符将从标准输入“缓冲”,直到看到EOF(ctrl-D)或换行符(LF),然后它将提供缓冲区中的所有字符加上特殊字符(EOF或LF)。我明白了。。。因此,每次调用
    getchar
    都会从缓冲区中删除一个字符(如果有)?是的。每个
    getchar
    检索一个字符。正如Jonathan在回答中指出的那样,我应该清楚EOF不是一个字符,而是一个
    -1
    值(
    int
    ),表示输入已结束。感谢您的洞察力!我希望得到这样的答案。因此,基本上,不是轮询,而是点击return会导致某个I/O中断,然后当操作系统接收到该中断时,它会唤醒任何正在休眠I/O的进程吗?编辑:或者更确切地说,当终端应用程序按下返回键时,它会向其子进程发送(软件)中断?(我对流程有点模糊,所以我可能说得不好。)感谢编辑和链接中提供的更多信息。你是个很好的作家。