• 从硬件+操作系统的角度解释为什么操作系统的IO单位是磁盘块


    不同版本的操作系统的 buffer_head 代表的大小可能不一样,但是都是内存和硬盘交换数据的基本单元。

    意思是:每次磁盘驱动程序,能写入到硬盘缓存区的数据大小 = buffer_head 代表的大小,线程会等待磁盘缓冲区的内容真正刷入扇区中

    写入完成后再唤醒线程,再次将一个块写入到磁盘缓冲区。

    我们用旧一点的 Linux 版本验证一下,下图出自 毛德操的《Linux源代码情景分析》

    在磁盘的驱动程序向磁盘相关的控制寄存器写入控制信息之后(写入起始扇区号,读还是写等信息)

    能向硬盘的写入的 字(16位)数是固定的 一个扇区的字节数,总共写入的字节数 = 扇区大小 * 2

    当前语境下的 buffer_head 是 1024 字节,扇区是 512 字节,也就是磁盘块 1024 字节,扇区 512 字节,写入磁盘缓冲区的大小就是磁盘块的大小

    随后驱动程序再次写相关的控制寄存器,开启真正的磁盘IO,使得磁盘缓冲区内容写入物理扇区,在此期间写入数据的IO进程如果是阻塞模式需要等待写入完成。

    磁盘缓冲区写入到扇区完成后会发出中断,中断程序会唤醒IO进程,IO进程再将下一个 buffer_head 写入磁盘缓冲区,重复上述步骤,这种频繁唤醒睡眠的机制很低效,在新版本应该有优化

    驱动程序是硬件厂商(当前考虑硬盘)结合目标操作系统编写的,需要依赖目标操作系统的数据结构(结构体定义),那么也就可以硬件厂商会根据 linux 不同版本的 buffer_head 的大小,还要自己制造的硬件的规格,控制一次能写入磁盘缓冲区的数据大小,让他刚好等于 buffer_head,遵循 linux 的初衷。

    节点大小为一个磁盘块,使得一次IO操作就能完成一个节点的写入,读/写一个块 只用一次 中断唤醒,提高效率

    关于中断程序和驱动程序的区别:

    驱动程序

    主要负责对硬件设备的读写,因为不同硬件制造厂商制造硬件的规格各不相同,就要按照自己的规格结合目标操作系统写出良好的驱动程序。

    读写当然属于硬件规格的范畴,而且多事一些对控制寄存器和数据寄存器的读写操作(如果操作系统支持 in,out 指令,输入输出几乎都用in ,out)

    包括写外设的某些控制寄存器,以准备读写,以及把数据写出到硬件的数据寄存器(CPU拷贝)
    或者开启 DMA 进行数据拷贝

    中断程序

    以硬盘为例,当硬盘读数据到硬盘硬件上的缓存区(应该是寄存器组)完毕,就会通过硬件中断让CPU调用 读取中断程序,主要是拷贝
    硬盘缓冲区上的数据到内存中的缓存页上

    唤醒在缓冲页上等待的进程,因为进程要读取/写某个缓存页,并且阻塞的话,会进入buffer的
    等待队列,中断程序做的就是唤醒他
    如果还有已经从磁盘缓冲区读到内存的缓存页待操作,就调整req的下一个缓存页,处理下一个请求页(唤醒该页上等待的进程等)

    如果是写入完成,会把缓存页的干净标志设为1

    一个请求可能请求 N 个扇区,但是一次中断只完成了 M 个扇区的读取,这次中断只能从硬盘缓冲区拷贝 M 个缓存页到 内存
    接下去的 N - M 仍然需要多个中断程序来完成

    不同缓冲区可能对应连续的扇区,但是还是得按缓冲区为单位操作,每次只能读/写一个缓冲区(buffer_head)

  • 相关阅读:
    完美图解教程 Linux环境VNC服务安装、配置与使用
    c语言中<stdbool.h>的使用
    UNIX文件结构(转自UNIX/AIX操作系统基础教程)
    umask
    在AIX环境为Oracle表空间增加裸设备(逻辑卷)
    面的面积大小合线的长度的判断。
    不用新浪博客了。以后的日常感悟也在这里写了, 新浪太烂了。 (感叹也没用,什么都写不出来。 )
    轴心工具的做法。
    选择因素随机的判断。
    上面发的那个完整版变量还有问题,难道我不是用英文输入法, 电脑不说谎 ,看来我是大意了。下面是最终版。
  • 原文地址:https://www.cnblogs.com/lqlqlq/p/13991600.html
Copyright © 2020-2023  润新知