关于getchar()循环如何在内部工作的困惑

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

程序调用getchar()时究竟发生了什么

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

  1. 调用getchar时,它会检查STDIN缓冲区以查看是否有任何输入。
  2. 如果没有任何输入,getchar会睡觉。
  3. 唤醒后,getchar会检查是否有任何输入,如果没有,则让它自己再次进入睡眠状态。
  4. 重复步骤2和3,直到有输入。
  5. 一旦有输入(按照约定在结尾处包含’EOF’),getchar返回此输入的第一个字符并执行某些操作以指示下一次调用getchar应该从同一缓冲区返回第二个字母? 我不太确定那是什么。
  6. 当除了EOF之外没有其他字符时,getchar是否会刷新缓冲区?

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

 #include  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; } 

步骤2-4稍微关闭。

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

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

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

因此,基本上,而不是轮询,是命中返回会导致某个I / O中断,然后当操作系统收到此信息时,它会唤醒所有正在为I / Ohibernate的进程吗?

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

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

我说“名义上”是因为有一个外部机会,实际上终端应用程序确实通过pty(伪tty)调解I / O,但我认为它发生在内核级别并且终端应用程序涉及到相当晚处理。 键入的键盘和键入的显示器之间存在巨大的脱节。

另请参见Canonical与非规范终端输入 。