IO控制方式

1. IO控制器

  • CPU无法直接控制IO设备,IO设备由IO控制器来控制,但CPU可以控制IO控制器
  • CPU可以控制IO控制器,IO控制器来控制IO设备

1.1 IO控制器的组成

  • CPU与控制器之间的接口
  • IO逻辑
  • 控制器与设备之间的接口(一个控制器可以连接多个设备)

1.2 IO控制器的功能

  • 接收设备CPU指令:CPU的读写指令和参数存储在控制寄存器中。
  • 向CPU报告设备的状态:IO控制器中会有相应的状态寄存器,用于记录IO设备的状态。(如某位置为1表示忙碌,置为0表示就绪)
  • 数据交换:数据寄存器,暂存CPU发来的数据和设备发来的数据
  • 地址识别:给每个寄存器编址,IO控制器可以通过CPU提供的地址来判断CPU是要读写哪个就寄存器。

2. 程序直接控制IO方式

  1. 通过系统调用write进入内核态
  2. CPU向IO控制器发出读指令,于是IO控制器启动具体设备,并将状态寄存器设置为1(表示数据未就绪)
  3. CPU不断轮询检查状态寄存器是否已经变成0
  4. IO设备准备好数据后,将数据传递控制器,并报告自身状态
  5. 控制器将设备输入的数据放到数据寄存器中,然后将状态变为0(已就绪)
  6. 此时CPU发现状态寄存器已经变为0,表明数据已经就绪,则CPU会将数据寄存器中的数据读入CPU的寄存器中。
时间CPUIO控制器
1CPU向IO控制器发送读命令(将控制指令写入IO控制器的控制寄存器中)
2CPU不断轮询IO控制器的状态寄存器是否改为0IO控制器向具体的设备发出读请求,并将自身的状态寄存器设为1,表示未就绪
3输入设备准备好数据后将数据传递给控制器,并报告自身的状态
4IO控制器将输入的数据放到数据寄存器中,同时将状态寄存器改为0,表示数据已就绪
5CPU检测的IO控制器的状态寄存器改为0,得知数据已就绪,则将IO控制器中的数据寄存器中的数据读入CPU的寄存器

2.1 特点

  • 实现简单,在读写指令之后,加上实现循环检查的一系列指令即可
  • CPU不断轮寻,长期处于忙等,CPU利用率低。
  • 一次传输一字的数据,如键盘。

3. 中断驱动IO

时间CPUIO控制器
1CPU向IO控制器发送读命令(将控制指令写入IO控制器的控制寄存器中)
2CPU切换线程/进程,处理其他事情。IO控制器向具体的设备发出读请求,并将自身的状态寄存器设为1,表示未就绪
3输入设备准备好数据后将数据传递给控制器,并报告自身的状态
4IO控制器将输入的数据放到数据寄存器中,同时将状态寄存器改为0,表示数据已就绪
5IO控制器向CPU发出IO中断请求
6CPU处理IO中断请求,检查IO控制器的状态,得知数据已经就绪,则将IO控制器中的数据寄存器中的数据读入CPU的寄存器

3.1 特点

  • CPU不用轮寻忙等,在数据未准备好可以去处理其他任务。CPU与IO控制器可以并行工作。
  • 一次还是只能传输一个字的数据
  • 用于字符设备的输入

4. DMA控制IO

4.1 当有了DMA控制器之后

  • CPU不直接控制IO控制器了,CPU控制DMA控制器
  • DMA控制器去控制IO控制器
  • IO控制器再去控制具体IO设备

4.2 DMA控制器的组成

  • DR:暂存从设备到内存或从内存到设备的数据
  • MAR:输入时表示数据应存放内存的什么地方,输出时表示要输出的内容在内存的什么地方
  • DC:数据计数器,表示还有多少字节的数据要读写
  • CR:命令/状态寄存器,用于存放CPU发来的IO命令或设备的状态

4.3 DMA控制IO的流程

时间CPUDMA控制器
1CPU向DMA控制器发送读命令,并告知DMA要读入的数据放在内存的起始地址,以及要读入多少字节(要满足每块字节的倍数)
2CPU切换线程/进程,处理其他事情。DMA控制IO控制器,进行相关的读取工作
5DMA控制器完成工作后向CPU发出IO中断请求
6CPU根据IO中断请求得知数据已经读入内存。然后根据需要再继续下一轮数据读取

4.4 特点 

  • 数据直接从IO设备读入内存,不需要借助CPU中转
  • 一次可以读入一块或连续多块
  • 用于块设备的IO读取。如读写磁盘。

5. IO缓冲区

5.1 从一次read操作分析IO缓冲区

  1. 用户进程第一次调用fgetc读一个字节
  2. fgetc函数通过系统调用read进入内核态
  3. cpu在内核态通过给DMA发送读取数据命令(然后CPU可以切换到其他任务上去执行)
  4. DMA利用IO控制器从磁盘读入1k字节的数据到内核缓冲区中
  5. DMA通过中断告知CPU读取数据已经完成
  6. CPU得知数据读取已经完成,它会将内核缓冲区中的1k数据复制C标准库为其打开的文件分配的IO缓冲区中。该IO缓冲区处于用户态(CPU完成从内核态到用户态切换)
  7. 返回给用户进程该IO缓冲区的第一个字节,并将读写位置移动到第二个字节
  8. 用户进程第一次调用fgetc函数完成。
  9. 用户第二次调用fgetc函数读取1个字节
  10. fgetc函数直接从该文件分配的IO缓冲区中取出第二个字节,并将读写位置移动到第三个字节处
  11. 用户进程第二次调用fgetc函数完成。(第二次调用过程中没有发生模式切换)

5.2 上述过程中用到的缓冲区

  • 内核缓冲区
    • 磁盘文件读取时,首先会将部分数据读入内核缓冲区。不能直接读入用户空间的IO缓冲区
    • 由磁盘数据拷入内核缓冲区,这个过程CPU可以交给DMA来完成,DMA只需要完成时给CPU一个通知即可。
  • C标准库的IO缓冲区
    • 他是属于用户空间的缓冲区
    • 它需要CPU将内核缓冲区的内容拷贝到用户空间的IO缓冲区
    • 由内核缓冲区到C标准库的IO缓冲区发生了模式切换
  • 还有一种用户程序定义的缓冲区
    • 程序中定义的用于接收数据的数组等
    • 他们也算一种缓冲区。用于从C标准库的IO缓冲区中复制多个字节到用户定义到数组中。
    • 由C标准库的IO缓冲区到用户自定义的缓冲区之间没有发生模式切换。

5.3 C标准库的IO缓冲区的缓冲区性质

  • 全缓冲
    • 如果缓冲区写满了就写入内核缓冲区。
    • 常规文件通常都是全缓冲
  • 行缓冲
    • 如果用户程序写的IO缓冲区的数据有换行,就把这一行写入内核缓冲区;或者用户IO缓冲区写满了,也会将IO缓冲区的数据写入内核缓冲区
    • 标准输入和标准输出对应终端设备时通常是行缓冲的
  • 无缓冲
    • 用户程序每次调用标准库函数做写操作时,都要通过系统调用写会内核。
    • 标准错误输出通常是无缓冲的
  • 补充
    • 调用标准库函数的写操作,一般都是写入内核缓冲区。当写入到内核缓冲区完成,则写操作就会返回。
    • 内核缓冲区的数据什么时候写入到磁盘是由操作系统控制的。
    • sync函数:只能保证标准库IO缓冲区数据刷新到内核缓冲区
    • fsync函数:保证将标准库IO缓冲区数据刷新到磁盘文件
    • flush函数:java中的,是对sync函数的封装,只保证刷新到内核缓冲区。
    原文作者:每一个不曾起舞的日子,都是对生命的辜负
    原文地址: https://blog.csdn.net/weixin_44390164/article/details/121511318
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞