5.12 实现细节

正如前述,在UNIX中,标准I/O库最终都要调用第3章中说明的I/O例程。每个I/O流都有一个与其相关联的文件描述符,可以对一个流调用 fileno 以获得其描述符。


#include <stdio.h>

int fileno(FILE *fp);

</stdio.h>

返回:与该流相关联的文件描述符。如果要调用 dupfcntl 等函数,则需要此函数。为了了解你所使用的系统中标准I/O库的实现,最好从头文件 开始。从中可以看到:FILE 对象是如何定义的,每个流标志的定义,定义为宏的各个标准I/O例程(例如 getc)。Kernighan 和 Ritchie〔1988〕中的8.5节含有一个简单的实现,从中可以看到很多UNIX实现的基本样式。Plauger〔1992〕的第12章提供了标准I/O库一种实现的全部源代码。4.3+BSD中标准I/O库的实现(由Chris Torek编写)也是可以公开使用的。

实例程序5-3为三个标准流以及一个与一个普通文件相关联的流打印有关缓存状态信息。注意,在打印缓存状态信息之前,先对每个流执行I/O操作,因为第一个I/O操作通常就造成为该流分配缓存。结构成员 _flag_bufsiz 以及常数 _IONBF_IOLBF 是由作者所使用的系统定义的。如果运行程序5-3两次,一次使三个标准流与终端相连接,另一次使它们重定向到普通文件,则所得结果是:


$ a.out

stdin, stdout和stderr都连至终端

enter any character

键入新行符

one line to standard error

stream = stdin, line buffered, buffer size = 128

stream = stdout, line buffered, buffer size = 128

stream = stderr, unbuffered, buffer size = 8

stream = /etc/motd, fully buffered, buffer size = 8192

$ a.out < /etc/termcap > std.out 2> std.err

三个流都重定向,再次运行该程序:


$ cat std.err

one line to standard error

$ cat std.out

enter any character

stream = stdin, fully buffered, buffer size = 8192

如果你对基于Unix的I/O函数的文件逆转程序感兴趣,可以查看 这个链接;若想了解C标准I/O库的粗略实现教程,点此 了解更多。标准C的I/O库函数实现文件逆转的信息请参阅 这里。对于文件I/O操作的全面讲解,可以访问 这篇文章。如果你对Python的文件I/O有兴趣,这篇 教程 也许会对你有帮助。