前言
学习自用,文末的参考资料都是好文,这篇还得慢慢补充
正文
linux IO,首先应该看一下linux IO涉及到的层次图,
对于read系统调用在内核的处理,如上图所述(TODO),经过了VFS、具体文件系统,如ext2、页高速缓冲存层、通用块层、IO调度层、设备驱动层、和设备层
为了方便,我们暂时只讨论上面的三部分,应用层,内核的page cache,负责IO调度的block layer
加这些层是为了一个缓冲,用户空间的层是为了减少用户态写入读出跳转内核态太频繁,而内核的page cache也是因为缓冲磁盘寻道时间,而mmap+write就是直接把这个区域映射到用户空间从而可以直接写入
block layer则是负责整理IO请求,即我们操作系统里学到的IO调度算法,block layer可以看成是DMA和硬件组成;
然后讲下常用的API
最常见的read 和write,如果是默认打开文件open的方式,一次read/write都会用到全部缓存,如果是open的时候传入了其它flag就另当别论了
还可以采用mmap+write的方式,这样的话可以忽略应用层的buffer直接写进内存中(这个mmap的空间估计能和page cache合并),不过每次写入内存都会陷入内核态,如果是太频繁的读写也会导致内核切换的开销太大,这正是用用户层buffer的原因
还有个问题是mmap会有安全性的问题,其他进程可能会写到这个位置而引起SIGBUS(这个不是隔离的吗,mmap都是所有进程可见的?)
另外几种有几种IO的API,比如fwrite,fclose,fflush,fsync
- fflush是把应用层的clib buffer刷入内核的page cache中,
- fsync函数可以把内核的page cache刷入磁盘中 ;
- fwrite是写到clib后返回了
- 当调用fclose的时候,也会刷入磁盘中
详细
详细讲下read/write,write的时候,会把数据写到page cache便返回调用,(剩下的靠DMA完成吧?),而read的时候,会把数据从page cache拿来返回,如果没有则阻塞等待
内核线程pdflush
page cache是否继续往下刷入就要靠内核线程了,这个内核线程叫pdflush线程,会不停的检测检测条件,条件成立则把需要写回的页提交到IO队列——即IO调度队列。IO调度队列调度策略调度何时写回。pdflush这里也有一些延申知识,看understanding linux kernel,这里不讲
几个判断的条件;就像innodb实现的一样,一是到一定数目则刷入,二是隔一定时间刷入
IO调度队列这边需要进行两个步骤,一个是合并相邻位置,二是按寻道方向位置排序不同调度作业
参考资料
- https://zhuanlan.zhihu.com/p/83398714(这个splice和sendfile没看啊)
- https://blog.youkuaiyun.com/u014106644/article/details/84565912真的好文章
- http://blog.chinaunix.net/uid-27105712-id-3270102.html上面的好文的出处吧
- https://mp.weixin.qq.com/s?__biz=MzAxNzU3NjcxOA==&mid=2650721579&idx=2&sn=cec1c32e0b570e52711d7dcee4a16dbe&