setvbuf 不改变缓冲区大小?

setvbuf not changing buffer size?

我有以下玩具代码来测试 I/O 在 fread 上的缓冲,我得到了我没有预料到的结果:

#include <stdio.h>
#include <stdio_ext.h>

int main()
{
    FILE *fp;
    char buff[255];
    fp = fopen("/home/install.sh", "r");
    int result = setvbuf(fp, NULL, _IOFBF, 700); // set buffering size to some arbitrary value, say 700
    printf("Result of setting buffer: %d\n", result ); // "Result of setting buffer: 0"
    printf("Buffer size: %zd\n", __fbufsize(fp) ); // "Buffer size: 4096"


    fread(buff, 255, 1, fp);
    printf("%s\n", buff ); // prints 255 bytes as I would expect

}

从上面看,setvbuf 调用似乎成功,因为它返回 0,但缓冲区大小保持在 4096。此外,我尝试打印出 BUFSIZ,它显示 8192。 运行 strace 确实将基础 read 调用显示为 4096 字节。关闭缓冲似乎工作正常,因为缓冲区大小设置为 1。

此外,我不明白为什么BUFSIZ8192)与这些读取的默认值(4096)不同。

我尝试了很多不同的缓冲区大小值,但都无济于事。

我是运行ldd (Ubuntu GLIBC 2.27-3ubuntu1) 2.27

我在这里阅读了以下内容 https://en.cppreference.com/w/c/io/setvbuf:

Not all size bytes will necessarily be used for buffering: the actual buffer size is usually rounded down to a multiple of 2, a multiple of page size, etc.

On many implementations, line buffering is only available for terminal input streams.

所以它可能不适用于您系统上的文件句柄。

如果它确实有效,我可以想象小于文件系统上分配单元大小的值没有多大意义(很可能是 8192)。

setvbuf not changing buffer size?

Glibc setvbuf implementation 只是在 mode == _IOFBFbuff == NULL 时忽略 size 参数。这很好 - 缓冲模式的特征是实现定义的。而 __fbufsize 是一个非标准的扩展名。通常你不应该依赖底层 FILE.

的缓冲

I don't understand why BUFSIZ (8192) is not the same as the default value of these reads (4096).

Glibc mmap the file. Because of mmap the size get's rounded to page size.