c - C 中的文件 IO 缓冲

标签 c buffering

我正在探索 C 中的 IO 缓冲区实现。我正在使用 Ubuntu 12.04/GCC。 对行缓冲的行为和触发底层系统调用 read() 的方式有疑问。我对行缓冲区实现的理解是,对 read() 的系统调用是在遇到流中的新行时完成的。 但是,如果您查看第一个 read(),它会读取 200 个字节。在另一个 read() 完成之前,第一次写入打印 114 个字符,因为第二次写入在流中有一个新行。 但是,如果您查看后续的 reads() ,它看起来不像是由换行符触发的。 无论是否在流中看到换行,它总是读取 200 个字节。附带说明一下,在第二次读取完成之前,流中已经有大约 90 个字符,当缓冲区大小为 200 时,它如何读取额外的 200 个字符。 注意:如果在 setvbuf 中将缓冲从行缓冲更改为完全缓冲,则输出完全相同。有人可以阐明为什么在线路缓冲应该如何触发底层系统调用时会出现这种行为吗?

代码如下:

#define     KBUFFER         200
#define     LBUFFER         100


int main(int argc, char *argv[])
{

    FILE *file;
    char lbuf[LBUFFER], kbuf[KBUFFER];

    if ((file = fopen("testing", "r")) == NULL){
        printf("Failed to open testing\n");
        exit(1);
    }


    // Set Line Buffer mode
    setvbuf(file, kbuf, _IOLBF, KBUFFER);

    while ( (fgets(lbuf, LBUFFER, file) != NULL ) ){
            printf("[%s]", lbuf);
    }

    return 0;
}

#

测试时每行110个字符;

strace 的输出是:

open("testing", O_RDONLY)               = 3

read(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 200) = 200

fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7064a98000

write(1, "[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"...,114[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa][aaaaaaaaaaa
) = 114

write(1, "]", 1])   
                 = 1
read(3, "bbbbbbbbbbbbbbbbbbbbb\ncccccccccc"..., 200) = 200

write(1, "[bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"..., 114[bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb][bbbbbbbbbbb
) = 114

write(1, "][cccccccccccccccccccccccccccccc"...,  115][ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc][ccccccccccc
) = 115

write(1, "]", 1])                        = 1

read(3, "dddddddddddddddddddddddddddddddd"..., 200) = 200

write(1, "[ddddddddddddddddddddddddddddddd"..., 114[ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd][ddddddddddd
) = 114

write(1, "][eeeeeeeeeeeeeeeeeeeeeeeeeeeeee"..., 115][eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee][eeeeeeeeeee
) = 115

write(1, "]", 1])  
                  = 1
read(3, "ffffffffffffffffffffffffffffffff"..., 200) = 200

write(1, "[fffffffffffffffffffffffffffffff"..., 114[fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff][fffffffffff
) = 114

write(1, "][gggggggggggggggggggggggggggggg"..., 115][ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg][ggggggggggg
) = 115

write(1, "]", 1])                        = 1

read(3, "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"..., 200) = 88

write(1, "[hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"..., 114[hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh][hhhhhhhhhhh
) = 114

write(1, "]", 1])                        = 1

read(3, "", 200)                        = 0

exit_group(0)  

#

最佳答案

Have a question on the way line buffering behaves and triggers underlying system call read()

读取总是缓冲在 C 库中。

行缓冲和其他缓冲模式仅适用于输出流。

关于c - C 中的文件 IO 缓冲,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20100818/

相关文章:

c++ - 如何从内存中正确读取数据(memcpy)

c++ - 在 C++ 中生成从 -K 到 K 的随机数 vector (大小为 M)

c - 15 拼图程序,卡在上下命令上

c - 标准 I/O 库的缓冲

ruby-on-rails - Rails——如何将 HAML 部分的 HTML 输出保存为字符串以发送到外部服务?

java - SWT ScrolledComposite 在 32768 像素后截断 canvas 生成的图像

php - SoapServer->handle() 忽略输出缓冲

c - K&R答题簿练习1.21

c - 为什么这个链表代码总是导致 head 为空?

Android - 如何判断 MediaPlayer 何时缓冲