流与缓冲区

我们通过讨论unix系统提供的I/O和ISO C中的标准I/O来引出我们所要讨论的流与缓冲区的概念。

系统I/O通常被称为不带缓冲的I/O,之所以这样说,是因为它们都调用内核中的一个系统调用。

相对于系统I/O函数,标准I/O库处理很多细节,如缓冲区的分配、以优化的块长度执行I/O等。这些处理使用户不必担心如何选择合适的块长度,使得它更便于用户使用。

所有系统I/O函数都是围绕文件描述符的,而对于标准I/O库,它们的操作则是围绕流(stream)进行的。

对于一个进程,通常预定义了3个流:标准输入,标准输出和标准错误。在系统I/O函数中,通常用STDIN_FILENO、STDOUT_FILENO和STDOUT_FILENO这3个文件描述符来表示。而在标准I/O库中则通过文件指针stdin、stdout和stderr来引用。当然,也可以用0、1、2来引用这3个流,不过这样有失可读性,看个人喜好了。


标准I/O库提供缓冲的目的是尽可能减少使用read和write系统调用的次数,而且它也对每个I/O流自动地进行缓冲管理,从而避免了应用程序需要考虑这一点所带来的麻烦。

标准I/O提供了以下三种类型的缓冲:


(1)全缓冲
在这种情况下,只有填满标准I/O的缓冲区后才进行实际的I/O操作。对于驻留在磁盘上的文件通常是由标准I/O库实施全缓冲的。在一个流上执行第一次I/O操作时,相关标准I/O函数通常调用malloc函数来获得所需的缓冲区。


(2)行缓冲
在这种情况下,当输入输出遇到换行符时,标准I/O库才执行I/O操作。这就允许我们一次输出一个字符,但只有在写满了一行之后才执行实际的I/O操作。当流涉及到终端时(如stdin和stdout),通常使用行缓冲。

对于行缓冲有两个限制。第一,每个行缓冲区的长度是固定的,所以只要填满了该缓冲区,哪怕还没有遇到换行符,也执行I/O操作。第二,任何时候只要通过标准I/O库从一个不带缓冲的流或者一个行缓冲的流中读取输入,就会先冲洗所有的行缓冲区。


(3)不带缓冲
标准I/O库不对字符进行缓冲存储。


标准错误流stderr通常是不带缓冲的,这样可以使错误信息尽快显示出来。若是指向终端设备的流,则是行缓冲的;否则是全缓冲的。


术语冲洗(flush)说明标准I/O缓冲区的写操作。缓冲区可由标准I/O例程进行冲洗(例如,当填满一个缓冲区时);在任意时刻,都可以调用fflush函数强制冲洗一个流。值得注意的是,在UNIX环境中,flush有两种意思。在标准I/O库方面,flush意味着将缓冲区中的内容写到磁盘上;在终端驱动程序方面,flush表示丢弃已存储在缓冲区中的内容。

猜你喜欢

转载自blog.csdn.net/qq_41145192/article/details/81232482
今日推荐