V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yezheyu
V2EX  ›  Unix

请教下关于 IO 缓冲的一点疑问

  •  
  •   yezheyu · 179 天前 · 515 次点击
    这是一个创建于 179 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在看《 unix 系统编程手册》和《 unix 环境高级编程》 看到 IO 缓冲区这块有点疑问,书上好多地方有提到缓冲区,但书上也没细说是内核缓冲区还是用户缓冲区 翻一下网上的帖子,发现也是如此。

    我按照个人理解画了下面几幅图,大家帮我看下我理解的对吗?

    read 函数:每次调用都执行一次 read 系统调用,没有缓存

    fread 函数:

    • 当 fopen 打开文件时会先在用户空间为其建立一个缓冲区,用于减少系统调用。
    • 第一次 fread 5 个字节时,实际先使用 read 系统调用读取 2k 数据,但只返回给 fread 5 个字节。
    • 第二次 fread 5 个字节时,只是从用户缓冲区接着再读 5 个字节返回给 fread ,并未调用 read 系统调用。
    • 当用户缓冲区中 2k 数据被消费完,会自动进行预读,从输入缓冲区再 read 2k 数据为下次 fread 做准备

    write 函数:每次调用都会执行一次 write 系统调用,没有缓存

    fwrite 函数:

    • 当 fopen 打开文件时会先在用户空间为其建立一个缓冲区(假设是行缓冲模式),用于合并系统调用。
    • 第一次 fwrite 5 个未含有换行符的字节时,只是先把这个 5 个 bytes 放入用户缓冲区,并未触发 write 系统调用。
    • 第二次 fwrite 5 个含有换行符的字节时,也是把这个 5 个 bytes 放入用户缓冲区,但因为含有换行符,触发了 write 系统调用,把用户缓冲区的数据拷贝到输出缓冲区,再交给 DMA 保存到磁盘

    我上面描述的对吗?

    输入输出缓冲区是位于内核空间吗?

    fopen 返回的 FILE 结构体是包含着用户缓冲区是吗?

    如果 fopen 以读写方式打开文件,那是不是会在用户空间同时建立两个缓冲区,一个用于读,一个用于写?

    fopen 打开文件返回的对象称之为 stream ,stream 是个啥?是不是其特点就是带有缓冲区,可以用于缓冲 IO ,合并系统调用?

    如果使用 setvbuf 把 fread 中的用户缓冲区改为行缓冲模式,那第一次 read 时是不是只从输入缓冲区读取一行数据而不是 2k ?

    test.txt 内容如下
    ab
    cd
    
    
    FILE *file = fopen("test.txt", "r+");
    char buf_cache[512];
    setvbuf(file, buf_cache, _IOLBF, 512);
    char c;
    sleep(5);
    fread(&c, 1, 1, file);
    fread(&c, 1, 1, file);
    fread(&c, 1, 1, file);
    fread(&c, 1, 1, file);
    fread(&c, 1, 1, file);
    fclose(file);
    
    

    那以上代码我用 strace 追踪为啥还是只调用了一次 read 系统调用呢?按理说不应该是因为有两行数据执行两次 read 吗?

    3 条回复    2023-10-31 10:54:39 +08:00
    zeonluang
        1
    zeonluang  
       179 天前
    “如果 fopen 以读写方式打开文件,那是不是会在用户空间同时建立两个缓冲区,一个用于读,一个用于写?”
    肯定是一个

    “按理说不应该是因为有两行数据执行两次 read 吗?”
    两行数据在同一个 page 里
    yezheyu
        2
    yezheyu  
    OP
       179 天前
    @zeonluang 是不是对于文件来说,如果文件数据比较小,page 的优先级是高于行缓冲模式?
    yezheyu
        3
    yezheyu  
    OP
       179 天前 via Android
    顶下帖
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2930 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 85ms · UTC 09:21 · PVG 17:21 · LAX 02:21 · JFK 05:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.