在CSAPP的第10.9节中,它说标准I / O流有两个限制,它们与套接字的限制不能很好地交互。
限制1:输入功能紧随输出功能。如果没有中间调用fflush,fseek,fsetpos或rewind,输入函数就不能跟随输出函数。 fflush函数清空与流关联的缓冲区。后三个函数使用Unix I / O lseek函数重置当前文件位置。
限制2:输出功能紧随输入功能。除非输入函数遇到文件结尾,否则输出函数不能跟随输入函数而不会介入fseek,fsetpos或rewind。
但是我不知道为什么要施加限制。所以,我的问题是:什么因素导致这两个限制?
它还说“在套接字上使用lseek函数是非法的。”,但是fseek
,fsetpos
和rewind
怎么可能使用lseek
重置当前文件位置(如果为true)?
有一个类似的问题here,但我的问题与此不同。
答案 0 :(得分:1)
stdio
函数用于缓冲文件的输入和输出。套接字不是文件,而是套接字。它甚至没有文件位置,并且缓冲区要求与普通文件完全不同-套接字可以具有独立的输入和输出缓冲区,而stdio文件I / O不能!
问题在于,文件输入和文件输出共享相同文件位置,并且操作系统可能具有(并且实际上会在Unix上具有),由于C中的缓冲,文件位置不同于文件位置。
因此,根据C99原理
仅在成功后才允许在更新文件上更改输入/输出方向
fsetpos
,fseek
,rewind
或fflush
操作,因为这些恰好是功能 这样可以确保已清空I / O缓冲区。
请注意,所有这一切仅适用于以+
打开的文件-在以任何其他标准模式打开的文件中,无法混合输入和输出。
由于C标准要求在FILE *
的功能之一fsetpos
上从 input 切换到 output 实际上尝试调用rewind
的1}}或fseek
必须成功(请注意,调用lseek
会刷新输出,而不是输入缓冲区!),然后才尝试输出函数...套接字是不可搜索的,因此fflush
总是失败-这意味着您不能同时使用lseek
打开和读写包装套接字的方式FILE *
读取和写入到套接字。
如果确实需要,可以使用fdopen
用流套接字打开FILE *
:只需打开 2 个文件-一个"rb"
作为输入和另一个和"wb"
用于输出。
答案 1 :(得分:0)
当它说“如果没有中间人对fflush,fseek,fsetpos或rewind的调用,输入函数就不能跟随输出函数”,这意味着如果您不这样做,则它可能无法按预期工作。但是他们主要是在谈论普通文件的输入/输出。
如果您有一个FILE *
流连接到套接字,并且想在读写之间来回切换,我希望如果您从切换时调用fflush
可以正常工作从写作到阅读。从阅读转换为书写时,我不希望有必要调用任何东西。
(处理文件时,必须致电fseek
或其亲戚之一才能正确更新文件位置,但是流中没有要更新的文件位置。)