IO—— Input Output简写 也就是常说的输入输出
我觉得这东西其实是相对而言的,比如我现在要用的是QQ文件上传,那相对于QQ这个应用而言,Input就是本地磁盘的文件到QQ应用,output就是本地QQ应用到QQ的服务器上
再比如我现在用java开发一个web后端,前端想从我这下载图片,相对于web后端而言,input就是文件服务器到后端服务器,output就是后端服务器到web前端
所以其实对IO来讲 讲的就是传输,可以简单的理解为输入输出流,用来传输字节。 根据不同的场景也分为不同的IO类型 作为开发人员最关心的莫过于网络IO/磁盘IO
我们从一个例子入手,
从本地磁盘读取一个字节 是怎样实现的?
我们在应用程序层发出指令 要读一个字节 调用c函数库,内核就需要 IO 引擎、VFS、PageCache、通用块管理层、IO 调度层等许多个组件来进行复杂配合才能完成。
最后传到硬件层也就是磁盘,磁盘进行转磁头啊寻址啊 找到数据。
完整的流程是这样的,但是linux内核面向用户黑盒的做了很多优化,用缓存的机制 多层缓存帮助我们尽量避免磁盘寻址 (磁盘寻址可不是最费力气的吗)
第一层缓存 PageCache
Page Cache。页高速缓存。是一个纯内存的工作组件。
Page Cache 是以页为单位的,Linux 页大小一般是 4KB (??这不就是mysql InnoDB索引的底层最小存储单位页吗 冥冥之中好像懂了什么..)
Linux 内核使用搜索树来高效管理大量的页面。
通过PageCache,Linux 就可以把一些磁盘上的文件数据保留在内存中,然后来给访问相对比较慢的磁盘来进行访问加速。
按照上图从上到下走,如果PageCache中命中,则不需要继续往下走
第二层优化 IO调度层
IO 请求到达这里时,并不一定会立即被执行。因为调度层会从全局出发,尽量让整体磁盘 IO 性能最大化。
对于机械硬盘来说,调度层会尽量让磁头类似电梯那样工作,先往一个方向走,到头再回来,这样整体效率会比较高一些。(也就是常说的电梯算法)
第三层缓存 磁盘缓存
这不属于linux层,由磁盘自带,,因为现在的磁盘本身就会带一块缓存。另外现在的服务器都会组建磁盘阵列,在磁盘阵列里的核心硬件Raid卡里也会集成RAM作为缓存。
读一个字节时IO会有多大?
整个 IO 过程中涉及到了好几个内核组件。而每个组件之间都是采用不同长度的块来管理磁盘数据的。
整个内核工作流中,最小的工作单位是磁盘的扇区,为512字节。 所以一次磁盘IO读取最小最小是读取一个扇区,也就是512字节
另外 block、page cache 等高层组件工作单位更大。其中 Page Cache 的大小是一个内存页 4KB。所以一般一次磁盘读取是多个扇区(512字节)一起进行的。
假设通用块层 IO 的段就是一个内存页的话,一次磁盘 IO 就是 4 KB(8 个 512 字节的扇区)一起进行读取。
最后,还有预读取策略(提前读前后数据到缓存中,方便连续读取) 所以一次磁盘IO读取理应是大于4K