请教下关于 IO 缓冲的一点疑问 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yezheyu
V2EX    Unix

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

  •  
  •   yezheyu 2023-10-30 17:51:27 +08:00 1166 次点击
    这是一个创建于 711 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在看《 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  
       2023-10-30 18:01:56 +08:00
    “如果 fopen 以读写方式打开文件,那是不是会在用户空间同时建立两个缓冲区,一个用于读,一个用于写?”
    肯定是一个

    “按理说不应该是因为有两行数据执行两次 read 吗?”
    两行数据在同一个 page 里
    yezheyu
        2
    yezheyu  
    OP
       2023-10-30 18:16:59 +08:00
    @zeonluang 是不是对于文件来说,如果文件数据比较小,page 的优先级是高于行缓冲模式?
    yezheyu
        3
    yezheyu  
    OP
       2023-10-31 10:54:39 +08:00 via Android
    顶下帖
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     938 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 22:08/a> PVG 06:08 LAX 15:08 JFK 18:08
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86