磁盘IO

作者:大宽宽
链接:https://www.jianshu.com/p/444646e02ef7
來源:
著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

对于磁盘来说,簇sector是其最小操作单位
磁盘的很多簇是512Byte 而cd的簇是2KB
对于linux,虚拟文件系统(VFS)抽象磁盘设备统一称为块设备(block device)
数据是按照一块块来组织的。操作系统可以随机定位到某个块,读写某个块
所以簇等价于块
page cache


pageCache.png

在VFS上面的是page cache
一般讲一个页面是4KB,页是其基本单位,一个页面对应若干块
系统的write方法写入数据到磁盘的流程是先写入page cache,此时page被称为脏页,其最终被写入到磁盘(这个过程称为写回)
写回不会立刻发生,有可能是由调用者使用了类似fsyn这样的api 或者操作系统根据自己的策略和算法自动写回,如果
在写回之前机器挂了就有可能丢数据。
当我们读取数据会先从page Cache里面找,找到了返回给应用程序,找不到返回页错误,然后去读取磁盘数据 然后在page cache进行缓存
Page Cache的基本维护算 =LRU


用户态和pagecache.png

如果你留意这个图,就会发现,这里会多额外两次数据的copy(并且是CPU copy)。但是有两种方法可以避免这两次copy,分别是mmap和sendfile。
mmap的一个巨大好处是可以让开发人员像是访问常规变量那样随机访问文件中的数据。如果不用mmap,开发人员就得自己用lseek去频繁定位文件的位置。这样一来是非常麻烦,代码写的会相当臃肿啰嗦;二是lseek也是系统调用,频繁使用的话会造成大量上下文切换,带来性能上的无谓损耗。

sendfile:有个严重的缺点。因为数据是两个fd在内核直接传输的,所以无法做任何修改。你只能原封不动的传输原始的数据文件。一旦你想在数据上做一些额外的加工,就无法使用sendfile


directio.png

Direct IO:即应用程序直接读写块设备,不再经过Page Cache。
应用场景:Direct IO必然会带来性能上的降低。所以Direct IO有特定的应用场景。比如,在数据库的实现中,为了保证数据持久,写入新数据到WAL(Write Ahead Log)必须直接写入到磁盘,不能等待。这里用Direct IO来实现WAL就非常理想。
应用程序对磁盘数据缓存有特别定制的需要,而常规的Page Cache的各种策略并不能满足这种需要。于是开发人员可以自己设计和实现一套“Cache”,配合Direct IO。毕竟最熟悉数据访问场景的,是应用程序自己的需求。
Direct IO有一个很大的问题是要求如果是写入到磁盘,开发者必须自行保证“块对齐”。即write时给的buffer的offset和size要刚好与VFS中的“块”对应,不然就会得到EINVAL错误。如果用了“Buffered IO”,Page Cache内部就可以自动搞定对齐这件事情了。没有Page Cache,对齐要就得自己做。比如,需要手工调用posix_memalign分配块对齐的内存地址。

你可能感兴趣的:(磁盘IO)