`read()`可以直接跟在`read()`和`read()`之间的`read()`吗?

在C标准库中,输出不能跟随输入,反之亦然。

对于Linux API, read()可以通过read()直接后跟write()write() read()吗? 如果是,为什么Linux API和C库IO API之间存在这样的差异?

谢谢。

你的另一个问题(链接)缺乏一些背景。 当它说“当打开文件进行读写(类型中的加号)时,有两个限制适用。”,它指的是使用FILE *流打开和操作的FILE * (例如, fopenfscanffprintf ,等) – 不是对文件描述符进行操作的(例如, openreadwrite等)。

只有FILE *流通常具有关联的stdio缓冲区; 文件描述符没有任何关联的缓冲区(可能有更低级别的其他缓冲区,如内核,磁盘控制器等 – 但这是你通常不必担心的事情)。 所以read(2)write(2)不缓冲任何东西(没有stdio缓冲区)。 所以他们没有这样的I / O订单限制。

回顾一下另一个答案,当使用stdio时,你正在使用一个不是实际文件的缓冲区。 如果您正在读取,则必须从实际文件中复制该缓冲区(通过OS read调用),如果您正在write ,则必须将其复制到实际文件中(通过OS write调用)。 如果你从写入读取过于仓促切换,stdio代码没有意识到它必须刷新写入的缓冲区并重新加载缓冲区以便读取。

另一方面,当使用write系统调用时,情况就不同了。 首先,您可能正在读取和编写设备(如串行端口或TCP网络流),在这种情况下,跳回和读写之间显然没有问题。

但即使您使用write系统调用来读写文件,您也可以直接访问该文件 – 或者至少是操作系统的文件概念。 没有提到stdio缓冲区的问题。

(具有讽刺意味的是,操作系统通常使用一个或多个文件块的缓冲副本。但实现完全不同,如果在读写之间来回切换,最终不会出现任何问题。 )

正如在另一个答案中所解释的那样, 可以编写stdio例程来支持交错的i / o,但为了简单和高效,它们不是。

为什么会这样? 另一个难题是,在C和Unix的早期,系统调用非常昂贵。 系统调用可能比普通函数调用长10或100倍。 因此,避免不必要的系统调用有一个真正的优势,stdio库是其中很重要的一部分。 它需要一次read调用来填充缓冲区,然后你可以进行大量的小调用来从缓冲区中取出单个(或少量)字符,而不会产生任何额外的开销。 类似地,在写入时,您可以进行大量的小调用来编写少量字符,然后只需要一次昂贵的write调用来刷新缓冲区。 stdio支持交叉读取和写入 – 这不是一个重要的用例 – 需要更多的系统调用,或更多的测试,或更多的代码(或所有三个),并且通常会比它更昂贵曾经值得。

(今天,系统调用的效率低得多,所以如果今天从头开始设计C和Unix,那么write系统调用与stdio输入和输出调用之间的区别可能会有所不同。)