获取相关联的文件描述符fd
#include <stdio.h>
int fileno(FILE *stream);
成功后,fileno()返回与流关联的文件描述符。如果失败,则返回−1。这只能在给定流无效时发生,在这种情况下,函数将errno设置为 EBADF。
通常不建议将标准I/O调用与系统调用混合。
特别是,一个好的做法是在操作文件描述符之前刷新流。
控制 Buffering
标准I/O实现了三种类型的用户缓冲,并为开发人员提供了一个控制缓冲区类型和大小的接口。不同类型的用户缓冲服务不同于不同的目的并且对于不同的场景是理想的。
- Unbuffered
不执行用户缓冲。数据直接提交给内核。由于这将禁用用户缓冲,从而否定任何好处,因此该选项不常用,只有一个例外: standard error。 默认情况下,是unbuffered。 - Line-buffered
缓冲是在每行的基础上执行的.对于每个换行符,缓冲区被提交到内核。行缓冲对于将流输出到屏幕是有意义的,因为消息会打印到屏幕上是用换行符分隔的。顺其自然地,这是连接到终端的流的默认缓冲,例如standard out。 - Block-buffered
缓冲是在每个块的基础上执行的,其中块是一个固定的字节数。它非常适合于文件。默认情况下, 与文件相关的所有流都是块缓冲的。标准I/O使用full buffering一词来表示block buffering。
大多数情况下,默认缓冲类型是正确和最优的。然而,标准I/O确实提供了一个接口来控制所使用的缓冲类型。
#include <stdio.h>
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
函数将流的缓冲类型设置为mode,该mode必须是以下内容之一:
- _IONBUF Unbuffered
- _IOLBF Line-buffered
- _IOFBF Block-buffered
除了_IONBF(在这种情况下,buf和size被忽略)之外,buf可以指向一个size字节大小的缓冲区,标准I/O将使用该缓冲区作为给定流的缓冲区。如果buf为null,则为size大小的缓冲区。 指定由glibc自动分配。
必须在打开流之后,但在对流执行任何其他操作之前,调用setvbuf()函数。它在成功时返回0,并且 否则为非零值。
当流关闭时,提供的缓冲区(如果有的话)必须存在。
块缓冲的默认缓冲区大小是BUFSIZ,定义在<stdio.h>中,通常是最佳选择(典型块大小的较大倍数)。
Thread Safety 线程安全
standard I/O函数本质上是线程安全的。
standard I/O操作是原子操作。
Manual File Locking
函数flockfile()等待流不再锁定,转储锁计数,然后获取锁,成为流的拥有线程,然后返回:
#include <stdio.h>
void flockfile(FILE *stream);
函数funlockfile()减少与流关联的锁计数:
#include <stdio.h>
void funlockfile(FILE *stream);
如果锁计数达到零,则当前线程将放弃流的所有权。另一个线程现在能够获得锁。
函数ftrylockfile()是flockfile()的非阻塞版本:
#include <stdio.h>
int ftrylockfile(FILE *stream);
如果流当前被锁定,ftrylockfile()将不执行任何操作,并立即返回一个非零值。如果流当前未被锁定,则获取锁,转储锁计数,成为拥有流的线程,并返回0。
flockfile (stream);
fputs ("List of treasure:\n", stream);
fputs (" (1) 500 gold coins\n", stream);
fputs (" (2) Wonderfully ornate dishware\n", stream);
funlockfile (stream);
Unlocked Stream Operation
实际上,它们是标准I/O的未锁定对应版本:
#define _GNU_SOURCE
#include <stdio.h>
int fgetc_unlocked (FILE *stream);
char *fgets_unlocked (char *str, int size, FILE *stream);
size_t fread_unlocked (void *buf, size_t size, size_t nr,
FILE *stream);
int fputc_unlocked (int c, FILE *stream);
int fputs_unlocked (const char *str, FILE *stream);
size_t fwrite_unlocked (void *buf, size_t size, size_t nr,
FILE *stream);
int fflush_unlocked (FILE *stream);
int feof_unlocked (FILE *stream);
int ferror_unlocked (FILE *stream);
int fileno_unlocked (FILE *stream);
void clearerr_unlocked (FILE *stream);
可以将锁定的开销降到最低,并提高性能。
除了不检查或获取与给定流关联的锁外,这些函数的行为都与其锁定的同级函数相同。
如果需要锁定,则程序员有责任确保手动获取和释放锁。
它们都是linux特有的。
Critiques of Standard I/O
标准I/O最大的投诉是双拷贝对性能的影响。
网友评论