最近我在读《Unix网络编程第一卷》。在3.9节中,图3.18最后两段说了,这里我引用一下:
...但是我们的建议是从黄油而不是行的角度来思考,编写代码来读取数据的黄油,如果需要一行,请检查缓冲区以查看它是否包含该行。
在下一段中,作者给出了一个更具体的例子,这里我引用一下:
...我们将在第 6.3 节中看到。像 select 这样的系统函数仍然不知道 readline 的内部缓冲区,因此粗心编写的程序很容易发现自己在 select 中等待已经接收并存储在 readline 缓冲区中的数据。
在6.5节中,实际的问题是“stdio和select()的混合”,这将使程序“容易出错”,这里我引用这本书。但如何呢?
我知道作者稍后在同一节中给出了答案,根据我对本书的理解,这是因为 select() 隐藏了数据,因此 select() 无法知道已读取的数据是消耗与否。
答案确实存在,但这里的第一个问题是我真的很难得到它,我无法想象它会对程序造成什么损害,也许我需要一个遇到这个问题的演示程序来帮助我理解它。
还是在第 6.5 节中,作者试图进一步解释这个问题,我在这里引用:
...考虑当标准输入有几行输入可用时的情况。select 将导致第 20 行的代码使用 fgets 读取输入,然后将可用行读入 stdio 使用的缓冲区中。但是,fgets 只返回一行,并将所有剩余数据留在 stdio 缓冲区中......
上面提到的“第20行”是:
if (Fgets(sendline, MAXLINE, fp) == NULL)
Run Code Online (Sandbox Code Playgroud)
其中 sendline 是 char 数组,fp 是指向 FILE 的指针。我查看了 Fgets 的详细实现,它只是用一些额外的错误处理逻辑包装了 fgets() ,仅此而已。
这是我的第二个问题,fgets 如何设法,在这里我再次引用,读取可用的行?我的意思是,我查阅了 fgets 的手册页,它说 fgets 通常在第一个换行符处停止。这不是意味着 fgets 只会读取一行吗?更具体地说,如果我在终端中输入一行并按 Enter 键,则 fgets 会读取这一行。我再次执行此操作,然后 fgets 读取下一个新行,并且该点一次一行。
感谢您耐心阅读所有描述,并期待您的答复。