曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4647|回复: 0
打印 上一主题 下一主题

[文件I/O] setvbuf() -- 设置 stdio 库所用的缓冲

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2012-11-22 16:03:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
setvbuf() 函数可用来控制 stdio 库所用的缓冲,其原型如下:
[C++] 纯文本查看 复制代码
#include <stdio.h>
int setvbuf(FILE *stream, char *buf, int mode, size_t size);

第 1 个参数 stream 表示对哪个文件流的缓冲修改。在该文件流打开后,setvbuf() 必须在任何作用在该流上的 stdio 库函数之前被调用。在 setvbuf() 被调用后,它所设置的缓冲特性也将影响到后续的 stdio 函数。

第 2 个参数 buf 和第 4 个参数 size 指定了 stream 所用的缓冲及其大小。buf 参数可以为 非NULL也可以为 NULL。当其非空时,它指向一块大小为 size 的内存块,该内存块被用作 stream 的缓冲。需要注意的是,这块内存块是被 stdio 库函数所使用,因此它应该是静态分配的或者是从堆中动态分配的(如用 malloc() 来分配),而不能是栈上的局部变量所分配的,否则会由于函数退出时栈被回收所带来的混乱与错误。

如果 buf 为 NULL,那么 stdio 库会自动为 stream 分配一个缓冲区(除非我们选择了非缓冲 I/O)。

第 3 个参数 mode 指定了缓冲的类型,它可以是下面的几个值:

1. _IONBF
该值表示不对 I/O 进行缓冲。每次调用 stdio 库函数时都会直接调用 read() 或 write() 进行读写,此时 buf 和 size 参数就被忽略掉,那么这时可以将 buf 指定为 NULL ,size 指定为 0 。stderr 标准错误默认就是使用该非缓冲特性的,因此可以保证错误信息能够马上被输出。

2. _IOLBF
该选项使用线缓冲(line-buffered) I/O 。实际上,对于适用于终端设备上的流就是默认使用了该属性。比如对于输出流,数据会先被缓存起来,直到遇到一个新行符输出。对于输入流,一次读取一行数据。

3. _IOFBF
该选项使用全缓冲I/O。在该模式下,数据是以缓冲区的大小作为读写单位的。对于作用域磁盘文件上的流来说,该模式是默认行为。

测试代码
[C++] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>

#define BUF_SIZE 1024

static char buf[BUF_SIZE];

int main(void)
{
        if (setvbuf(stdout, buf, _IOFBF, BUF_SIZE) != 0) {
                perror("setvbuf");
                exit(EXIT_FAILURE);
        }
        printf ("hello world\n");

        sleep(2);

        printf ("hello linux\n");

        sleep(2);

        fflush(stdout);

        return 0;
}

运行输出:
beyes@beyes  :~/c/setvbuf> ./setvbuf
hello world
hello linux
上面程序中,我们将 I/O 属性设置为全缓冲模式,而该缓冲区的大小为 1024 个字节。接着,使用了 2 次的 printf() 函数,在上面的情况下,printf() 函数要打印的字串不会马上输出,因为它们都被缓冲起来并且缓冲区里的内容还未达到 1024 个字节。因此,只有等待 4 秒后,使用 fflush() 函数强制刷新缓冲区后才会把上面两个字串输出来。

同样可以更换 mode 的模式来做实验,并可以观察到上面所描述的情况。

需要注意的是,函数如果执行失败,则返回非零值(不一定是 -1)。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-18 00:35 , Processed in 0.085187 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表