IO软件层次

操作系统IO部分给出的软件层次让我印象很是深刻,层级如同OSI参考模型一般。
各层封装相应功能并仅向上一层提供功能。文章还是以磁盘操作为例子,贯穿整个过程。

IO软件层次概览:

这里写图片描述

这是IO软件层次,而每层完成的大致功能:

这里写图片描述

中断处理程序理论上来说是很多过程共用的部分,做的工作主要如下:

  1. 通知上下文切换
  2. 通知进程切换时的资源保护
    但是中断程序做的工作的细节很多,中断的复杂性需要系统的整理,在此不加赘述。

我不认为用各个层次作为标题是一个好主意,应该用一个过程性的描述。

过程性描述:

1.你会在编程语言比如C++调用std::cout<<%2d variableName<<endl;,这是C++库<iostream>库中的库过程。上面这个代码产生IO请求,就是在第一层发生的。

假设此刻这个内存页框处于磁盘中,产生缺页中断后,会将从磁盘中读入原本在内存中的页框。这个页框中包含变量variableName。但是读磁盘的具体过程并非一句话的问题。
2.C++会调用操作系统读写磁盘的库过程。设备驱动程序和操作系统“其余部分”的接口是一类设备无关性接口。库过程会调用这些接口,将磁盘IO请求向下传递。

值得注意的是,接口的设计:
接口的设计应该尽量简洁有效标准化,并且不限制其他设计的可能性(扩展性)。
晦涩!额~
操作系统定义了一组磁盘驱动程序必须支持的接口(函数)。驱动程序包含一张表格,存储支持操作系统定义的接口函数地址。当驱动程序装载时,操作系统通过这张表来进行底层调用。给定类型的所有磁盘设备都应该支持此接口,以实现设备无关性。

这已经实现了标准化,而简洁有效性时函数设计过程中应该考虑的事情。而我所说的扩展性的意思是我认为这个函数表不应该是含有固定数目函数的表格,也就是说不排除一些特殊功能的实现。使用户通过简洁的地址函数调用,跳过内核而调用,可以完成一些标准化未更新但是需要的一些扩展性功能。

当然,如果标准化过程或者更新计划跟得上,这不应该是个额外鸡肋的工作。

双缓冲技术(double buffering)
双缓冲技术在此处有应用,java 全屏模式下用到这种双缓冲技术。
原理来说,很简单。就是在内核中放置两个缓冲区,一个缓冲区负责接受新的到来的位流,当缓冲区填满时将内核缓冲区中的内容复制到用户进程缓冲区中。考虑使用两个缓冲区的原因是防止这个复制过程中,因为缓冲区已满,而忽略掉新到来的位流。添加一个缓冲区,两个缓冲就可以形成一个相对封闭的环装模型,相辅相成。
这其实和另一种循环缓冲区在原理上相通。
循环缓冲
循环缓冲的底层数据结构是一个循环数组。头指针指向的字节是下一个要复制的,而尾指针指向的字节是新进来的。
这里写图片描述

之所以突兀的介绍这两种缓冲是因为缓冲技术是减少中断次数。对于没有缓冲区的模型,每一个到来的字符或字节都将引起中断,对于短暂的数据交换,这种设计简直浪费资源。

缓冲区的大小也是应该考虑的事情,不应该过大,这样会对于网络接口来说,会引起超时重传。

3.进入磁盘驱动程序读取寄存器内容,获得上层需求。磁盘驱动程序所完成的工作比如:磁盘坏块重映射,从逻辑磁盘块地址到实际磁盘块地址的转换,磁盘位流缓冲。 与OSI由区别的是,这一层驱动程序虽然不允许进行系统调用,但是可以与内核的一些函数过程进行调用。如通过MMU获取内存物理地址。 4.底层硬件完成工作,产生中断,交给中断处理程序。进程管理器在上下文切换成功后,对IO阻塞进程解除阻塞。 5.驱动程序重置寄存器状态。 6.IO接口程序进行数据缓冲,错误报告等工作,向上层传递IO应答。 7.内核返回调用信息给用户进程