块设备驱动程序

块设备驱动程序负责实现对块设备数据的读写功能。内核代码统一使用缓冲块间接和块设备(如磁盘)交换数据,缓冲区数据通过块设备驱动程序和块设备交换数据。

块设备的管理

块设备表

内核通过一张块设备表blk_dev[]管理各种块设备,每个表项对应一个块设备,并为每一个块设备维护一个请求队列。

  • current_request:指向设备请求队列第一个节点,请求队列通过链表实现。
  • request_fn:函数指针,用于处理请求队列里面的读写请求。

设备请求队列

内核为每个块设备维护一个请求队列,请求队列中请求等待被处理,current_request指向设备请求队列。

  • 请求项

用于描述请求操作,包含读写磁盘扇区位置信息、缓冲区地址信息、操作类别(读/写)信息等。

请求项数据结构:

  • 请求项数组

一块连续内存,被分割为请求项大小的块,形成数组,充当内存池的角色。请求队列中的请求项的内存从请求项数组中进行分配,请求操作完成后,请求项会被释放回该内存池中。

  • 请求队列

处理读写设备请求时,从请求项数组中获取一个空闲块,建立请求项,并插入设备请求队列中。

块设备操作方式

在内核与块设备进行数据交换(IO)时,涉及到三个对象之间的交互作用,其中主要需要了解系统和控制器之间的交互过程。

  • 系统(内核):内核可以向控制器发送命令(发出请求)或等待设备控制器发出中断请求(完成请求)。
  • 控制器:完成读写操作后,向系统(CPU)发出中断。
  • 驱动器:受设备控制器控制

写数据过程

  1. 系统向控制器发出写命令后,等待块设备准备好接收数据,期间CPU需要主动查询控制器的状态寄存器判断是否准备好接收数据(忙等待)。
  2. 控制器准备好后,CPU将数据写入控制器的缓存中。(控制器具有一块缓存)
  3. 控制器将缓存中的数据通过驱动器全部写入块设备。
  4. 向CPU发出中断,中断处理程序完成写数据后的处理

读数据过程

  1. 向控制器发出读命令
  2. 控制器读取磁盘数据到其缓存中
  3. 向系统发起中断,中断处理程序从控制器缓存中取走数据

请求队列处理过程

ll_rw_block函数将请求放入块设备请求队列,设备中断处理程序会不断处理请求队列,直到队列为空。

  • 写请求的处理过程
  1. ll_rw_block为写请求建立请求项,并插入设备的请求队列。若插入前队列为空,则调用请求项操作函数(request_fn)处理当前写请求,对块设备进行写操作。

  2. 设备块设备完成一个写请求后,向CPU发出中断信号,CPU运行中断处理函数。

  3. 中断处理程序判断是否还有数据要写(一个请求会可能写多个扇区),如果有则继续写,然后等待下一次中断,这一过程重复直到该写请求数据全部写入设备。

  4. 完成数据写之后,中断处理程序将唤醒一些等待进程

    • 唤醒等待该请求项有关数据的相关进程
    • 唤醒等待请求项的进程(当内存池没有空闲请求项时,将导致某些请求读写的进程睡眠)
    • 释放当前请求项并从链表中删除该请求项以及释放锁定的相关缓冲区。
  5. 唤醒等待进程后,中断处理程序将调用请求项操作函数处理下一个读/写请求

  • 读请求处理过程

与写请求处理过程类似

  • ll_rw_block与中断处理程序

ll_rw_block,负责将读写请求放入队列中,并启动对请求队列的处理。

中断处理程序,设备完成读写操作后,发出中断,不断处理请求队列中的请求操作,直到请求队列为空。

相关知识

  • I/O调度算法,读写请求不是按访问顺序放入请求队列的,0.11内核使用电梯算法调度读写请求

总结

  • 每个块设备具有一个请求队列,对块设备的读写请求被插入到队列中。
  • 中断处理程序不断处理请求队列中的请求,直到队列为空。完成某个请求后,会唤醒一些等待的进程。

Linux 0.11源码阅读笔记-块设备驱动程序的更多相关文章

  1. Linux 0.11源码阅读笔记-文件管理

    Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件. 磁盘分区 生磁盘可以被分区,分区中可以安装文件系统, ...

  2. Linux 0.11源码阅读笔记-中断过程

    Linux 0.11源码阅读笔记-中断过程 是什么中断 中断发生时,计算机会停止当前运行的程序,转而执行中断处理程序,然后再返回原被中断的程序继续运行.中断包括硬件中断和软件中断,硬中断是由外设自动产 ...

  3. Linux 0.11源码阅读笔记-总览

    Linux 0.11源码阅读笔记-总览 阅读源码的目的 加深对Linux操作系统的了解,了解Linux操作系统基本架构,熟悉进程管理.内存管理等主要模块知识. 通过阅读教复杂的代码,锻炼自己复杂项目代 ...

  4. Linux 0.11源码阅读笔记-总结

    总结 Linux 0.11主要包含文件管理和进程管理两个部分.进程管理包括内存管理.进程管理.进程间通信模块.文件管理包含磁盘文件系统,打开文件内存数据.磁盘文件系统包括空闲磁盘块管理,文件数据块的管 ...

  5. Linux 0.11源码阅读笔记-文件IO流程

    文件IO流程 用户进程read.write在高速缓冲块上读写数据,高速缓冲块和块设备交换数据. 什么时机将磁盘块数据读到缓冲块? 什么时机将缓冲块数据刷到磁盘块? 函数调用关系 read/write( ...

  6. Linux 0.11源码阅读笔记-高速缓冲

    高速缓冲 概念 高速缓冲区是内存中的一块内存,在块设备与内核其它程序之间起着一个桥梁作用.内核程序如果需要访问块设备中的数据,都需要经过高速缓冲区来间接的操作. 高速缓冲区结构 高速缓冲区被划分为1k ...

  7. Linux 0.11源码阅读笔记-内存管理

    内存管理 Linux内核使用段页式内存管理方式. 内存池 物理页:物理空闲内存被划分为固定大小(4k)的页 内存池:所有空闲物理页组成内存池,以页为单位进行分配回收.并通过位图记录了每个物理页是否空闲 ...

  8. 【从头到脚品读 Linux 0.11 源码】第一回 最开始的两行代码

    从这一篇开始,您就将跟着我一起进入这操作系统的梦幻之旅! 别担心,每一章的内容会非常的少,而且你也不要抱着很大的负担去学习,只需要像读小说一样,跟着我一章一章读下去就好. 话不多说,直奔主题.当你按下 ...

  9. linux 0.11 源码学习+ IO模型

    http://www.cnblogs.com/Fredric-2013/category/696688.html

随机推荐

  1. js websocket断线重连

    js websocket断开重连实例代码,请根据自己需求做出相应改动Vue中使用websocket $(function() { var lockReconnect = false;//避免重复连接 ...

  2. 01-RocketMQ介绍

    一.MQ介绍 1.什么是MQ?为什么要用MQ? MQ:MessageQueue,消息队列. 队列,是一种FIFO 先进先出的数据结构.消息由生产者发送到MQ进行排队,然后按原来的顺序交由消息的消费者进 ...

  3. 01-Servlet 回顾

    通过url访问资源有三个步骤: 接收请求 处理请求 响应请求 web服务器:将某个主机上的资源映射为一个URL供外界访问,完成接收和响应请求 servlet容器:存放着servlet对象(由程序员编程 ...

  4. mysql-索引对性能影响

    1.添加索引后查询速度会变快 mysql中索引是存储引擎层面用于快速查询找到记录的一种数据结构,索引对性能的影响非常重要,特别是表中数据量很大的时候,正确的索引会极大的提高查询效率.简单理解索引,就相 ...

  5. SQL从零到迅速精通【实用函数(3)】

    1.LOWER()函数 使用LOWER函数将字符串中所有字幕字符转换为小写,输入语句如下. SELECT LOWER('BEAUTIFUL'),LOWER('Well'); 2.UPPER()函数 S ...

  6. MySQL启动报错Failed to open log (file 'D:\phpStudy\PHPTutorial\MySQL\data\mysql_bin.000045', errno 2)

    MySQL报错 191105 9:39:07 [Note] Plugin 'FEDERATED' is disabled. 191105 9:39:07 InnoDB: The InnoDB memo ...

  7. dedeCMS自定义dede标签

    在include/taglib文件夹中新建文件hlh.lib.php,其中hlh也就是你标签的名字,function的名字也必须跟文件名对应,固定格式lib_标签名,如lib_hlh,本例子以调取文章 ...

  8. vue 组件间的几种通信方式

    Props配置 原理:通过props配置,进行父子组件间的通信,跨父子通信需要其他组件进行过渡. 使用: 传递方在标签中添加传递内容 <Son :newName="name" ...

  9. iscsi挂载

                                                                         iscsi挂载 1.server端:   (1) yum -y ...

  10. Gradle依赖声明类型

    compileOnly -用于编译生产代码所必需的依赖关系,但不应作为运行时类路径的一部分 implementation(取代compile)-用于编译和运行时 runtimeOnly(取代runti ...