关于getchar()循环如何在内部工作的困惑
我已经在下面使用getchar()
包含了一个示例程序,供参考(并不是任何人可能需要它),如果您愿意,可以随意解决它的问题。 但我的问题是:
程序调用getchar()
时究竟发生了什么 ?
以下是我的理解(请澄清或纠正我):
- 调用getchar时,它会检查STDIN缓冲区以查看是否有任何输入。
- 如果没有任何输入,getchar会睡觉。
- 唤醒后,getchar会检查是否有任何输入,如果没有,则让它自己再次进入睡眠状态。
- 重复步骤2和3,直到有输入。
- 一旦有输入(按照约定在结尾处包含’EOF’),getchar返回此输入的第一个字符并执行某些操作以指示下一次调用getchar应该从同一缓冲区返回第二个字母? 我不太确定那是什么。
- 当除了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-D或Control-Z来指示’EOF’,该字符也不会插入到输入流中。 实际上,这些字符会导致系统刷新仍在等待“行编辑”操作的任何类型字符(如退格键)以更改它们,以便它们可供read()
系统调用使用。 如果没有这样的字符,则read()
返回0作为可用字符的数量,这意味着EOF。 然后getchar()
返回值EOF
(通常为-1
但保证为负数,而有效字符保证为非负数(零或正数))。
因此,基本上,而不是轮询,是命中返回会导致某个I / O中断,然后当操作系统收到此信息时,它会唤醒所有正在为I / Ohibernate的进程吗?
是的,点击Return触发中断,OS内核处理它们并唤醒正在等待数据的进程。 当中断发生时,内核会唤醒终端驱动程序,并决定如何处理刚收到的字符。 它们可能被藏匿以进行进一步处理(规范模式)或立即可用(原始模式)等。当然,假设输入是终端; 如果输入来自磁盘文件,它在很多方面更简单 – 或者如果它是管道,或者……
名义上,终止应用程序不会被中断唤醒; 它是首先唤醒的内核,然后在终端应用程序中运行的shell被唤醒,因为它有数据供它读取,并且只有在输出时终端应用程序被唤醒。
我说“名义上”是因为有一个外部机会,实际上终端应用程序确实通过pty(伪tty)调解I / O,但我认为它发生在内核级别并且终端应用程序涉及到相当晚处理。 键入的键盘和键入的显示器之间存在巨大的脱节。
另请参见Canonical与非规范终端输入 。