3

In book CSAPP section 10.9, it says that there are two restrictions on standard I/O streams that interact badly with restrictions on sockets.

Restriction 1: Input functions following output functions. An input function cannot follow an output function without an intervening call to fflush, fseek, fsetpos, or rewind. The fflush function empties the buffer associated with a stream. The latter three functions use the Unix I/O lseek function to reset the current file position.

Restriction 2: Output functions following input functions. An output function cannot follow an input function without an intervening call to fseek, fsetpos, or rewind, unless the input function encounters an end-of-file.

But I cannot figure out why the restrictions imposed. So, my question is: what factors result to the two restrictions?

It also says that "It is illegal to use the lseek function on a socket.", but how is it possible fseek, fsetpos and rewind use lseek to reset the current file position if it is true?

There is a similar question here, but my question different from this one.

4

2 回答 2

2

这些stdio函数用于缓冲文件输入和输出。套接字不是文件,而是套接字。它甚至没有文件位置,而且缓冲区要求与普通文件完全不同——套接字可以有独立的输入和输出缓冲区,而 stdio 文件 I/O 则不能!

问题是文件输入文件输出共享相同的文件位置,并且由于 C 中的缓冲,操作系统可能具有(并且实际上在 Unix 上将具有)与文件位置不同的文件位置。

因此,从 C99 的基本原理

fsetpos只有在成功的 、fseekrewind或操作之后才允许更改更新文件的输入/输出方向 fflush,因为这些正是确保 I/O 缓冲区已被刷新的函数。

请注意,所有这些仅适用于打开的+文件 - 以任何其他标准模式打开的文件,不可能混合输入和输出。

由于 C 标准要求在函数, or上从输入切换到输出时,本质上调用必须成功(请注意,调用会导致写入缓冲的输出,并且肯定不会丢弃缓冲的输入)在尝试输出函数之前...但是套接字是不可搜索的,因此总是会失败- 这意味着您不能使用已为读写打开的套接字来实际读取写入套接字.FILE *fsetposrewindfseeklseekfflushlseekFILE *


如果您确实需要,可以使用带流套接字fdopen打开一个:只需打开两个文件 - 一个用于输入,另一个用于输出。FILE *"rb""wb"

于 2018-10-17T08:26:20.193 回答
0

当它说“如果没有对 fflush、fseek、fsetpos 或 rewind 的干预调用,输入函数不能跟随输出函数”,这意味着如果不这样做,它可能无法按预期工作。但他们主要谈论的是普通文件的 i/o。

如果您有一个FILE *连接到套接字的流,并且您想在写入和读取之间来回切换,那么如果您fflush在从写入切换到读取时调用它,我希望它可以正常工作。我不希望在从阅读切换到写作时调用任何东西。

(在处理文件fseek时,为了正确更新文件位置,需要调用或调用其亲属之一,但流没有要更新的文件位置。)

于 2018-10-17T10:35:17.037 回答