宋宝华: 文件读写(BIO)波澜壮阔的一生

点击上方 “公众号” 可以订阅哦!

前言


网上关于BIO和块设备读写流程的文章何止千万,但是能够让你彻底读懂读明白的文章实在难找,可以说是越读越糊涂!

我曾经跨过山和大海 也穿过人山人海

我曾经问遍整个世界 从来没得到答案

本文用一个最简单的read(fd, buf, 4096)的代码,分析它从开始读到读结束,在整个Linux系统里面波澜壮阔的一生。本文涉及到的代码如下:

#include <unistd.h>

#include <fcntl.h>

 

main()

{

        int fd;

        char buf[4096];

    

        sleep(30); //run ./funtion.sh to trace vfs_read of this process

        fd = open("file", O_RDONLY);

        read(fd, buf, 4096);

        read(fd, buf, 4096);

}

本文的写作宗旨是:绝不装逼,一定要简单,简单,再简单!


本文适合:已经读了很多乱七八糟的block资料,但是没打通脉络的读者;

本文不适合:完全不知道block子系统是什么的读者,和完全知道block子系统是什么的读者


Page cache与预读


在Linux中,内存充当硬盘的page cache,所以,每次读的时候,会先check你读的那一部分硬盘文件数据是否在内存命中,如果没有命中,才会去硬盘;如果已经命中了,就直接从内存里面读出来。如果是写的话,应用如果是以非SYNC方式写的话,写的数据也只是进内存,然后由内核帮忙在适当的时机writeback进硬盘。

代码中有2行read(fd, buf, 4096),第1行read(fd, buf, 4096)发生的时候,显然”file”文件中的数据都不在内存,这个时候,要执行真正的硬盘读,app只想读4096个字节(一页),但是内核不会只是读一页,而是要多读,提前读,把用户现在不读的也先读,因为内核怀疑你读了一页,接着要连续读,怀疑你想读后面的。与其等你发指令,不如提前先斩后奏(存储介质执行大块读比多个小块读要快),这个时候,它会执行预读,直接比如读4页,这样当你后面接着读第2-4页的硬盘数据的时候,其实是直接命中了。

所以这个代码路径现在是 :

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值