我正在探索 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/