文章目录

  • 概述
  • 磁盘
    • 磁道 扇区 柱面
    • 磁盘如何工作
  • 从柱面磁头扇区到盘块号
  • 多进程使用盘块号
  • 从文件字符流到盘块号
  • 从目录到文件
  • 从open系统调用到柱面磁头扇区
  • 总结
  • 参考资料

概述

  上篇只讲原理,不涉及代码,下篇将从代码层面进行讲解
  虽然标题是从系统调用到柱面磁头扇区,但我们知道,操作系统是联系硬件和用户的一个中间层,为用户操作硬件提供了方便和高效,操作系统的任何操作最终都会落实到硬件(这里是磁盘)上,所以我选择了从硬件开始讲起,看操作系统是如何一步一步把磁盘抽象为最终的文件系统的,反过来也就是用户如何通过文件系统来达到操作磁盘的目的。

磁盘

先来看一下磁盘的物理结构
  通过下方的图片,我们可以知道磁盘是由盘面,磁头,磁臂组成的,其他的磁道,扇区,柱面是人为的划分,物理上只由盘面磁头磁臂组成。

磁道 扇区 柱面

  可以看到磁盘是一个圆盘,由许许多多的同心圆组成,那么这每一个同心圆就是一个磁道。

  从中心转轴向外划分直线,可以把圆盘划分为一个个的圆弧,那么这每个圆弧就是一个扇区,典型的扇区大小是512个字节(最内侧磁道的扇区面积最小,因此数据密度最大)。

  可以看到磁盘是由很多盘面组成,所有盘面上的同一个同心圆(磁道)组成了一个柱面图,那么这就是柱面的概念,为什么要这么麻烦的弄出一个柱面的概念呢,稍后我们就会讲到,实际上这是因为磁臂的移动时间是很长的,为了尽量减少磁臂的移动时间,要在不移动磁臂的情况下读写磁盘,那么不移动磁臂时相同的磁道和扇区就组成了一个个的柱面,从而引出了柱面的概念。

磁盘如何工作

  我们已经知道,磁盘是由磁臂、磁头、柱面、扇区组成的,而且磁盘的读写是以扇区为单位,那么硬件被告知柱面磁头扇区这几个硬件的位置时,就开始进行电生磁的读入内存或者磁生电的写到磁盘。

从柱面磁头扇区到盘块号

  经过上面的讨论,我们知道了用户需要清楚柱面磁头扇区的位置才能对硬件进行操控,这样对使用磁盘极其的不方便,那么有没有什么方法来简化这种操作呢。答案是有的,那就是把零散的分布在各个盘面上的扇区按某种顺序对它们进行编码,利用这个编码来对它们进行操作,这个编码就是盘块号。
  ok,那需要按怎样的顺序对它们进行编码才能做到快捷高效呢,注意我们的目的不仅是方便,而且还要尽可能的做到快捷和高效,那怎样才能做到高效和省时呢,那我们就需要知道时间花在哪里,请看这个公式:
  磁盘访问时间(约10ms)=写入控制器时间+寻道时间(8-12ms)+旋转时间(半周4ms)+传输时间(0.3ms)
  可以看到,时间主要花在了寻道时间,也就是磁臂的移动时间,那为了省时,就需要在尽量少移动磁臂的情况下对扇区进行读写,这包含了两种方法,一种是尽量不移动磁臂进行读写,一种是一次尽量读写多个扇区。一次读写扇区数越多,那么相对效率就越高,如:磁盘访问时间为10ms,每次读写1k,碎片0.5k,读写速度为100k/s。每次读写1M,碎片0.5M,读写速度约40M/s,基于这个原理,linux0.12中是把每两个扇区作为一个盘块号进行编码的。不移动磁臂和磁头的话,相同的磁道在所有盘面上就构成了一个柱面,也就是我们柱面的概念。所以最终的编码方式是:先按柱面,把一个盘面上的一个磁道按顺序排列,因为此时读其他柱面需要旋转磁臂,一个柱面由多个磁头,所以接下来读相同柱面上的下一个磁道,这样对整个柱面后排列完成后再对下一个柱面进行排列,对下一个柱面进行类似的编码,直至对磁盘全部编码完毕。
  那么由上面对扇区编码完毕后,具体怎样计算呢。假设我们的磁盘要查找第c个柱面上第H个磁道上第S个扇区,那对应的盘块号就等于:
  C*(Heads* Sectors)+H*Sectors+S=block
  上方公式的Heads和Sectors分别代表每个柱面上的磁头数和每个磁道上的扇区数,是固定的数据,是在买磁盘的时候就已经确定好的常量。
  有了这个公式,那我们轻而易举的可以根据block号来算出对应的柱面磁头扇区号,所以现在,用户只需要向os提供盘块号,接下来的工作就可以由os来完成,间接达到了操控硬件的目的。

多进程使用盘块号

  上面讲解了单进程通过盘块号来完成,但我们知道,现代操作系统都是多进程。有多进程的地方,就会有竞争条件,这里也不例外,我们要怎样避免竞争条件呢,答案是使用请求队列。
  通过把对磁盘的请求组织成请求结构(struct request),并把多个请求结构组织成请求队列,由磁盘驱动从请求队列中拿出请求进行操作。那么这个请求结构主要包含的就是起始扇区号,读写命令,读写扇区数,有了起始扇区号,我们就可以根据前面讲到的公式来得到柱面磁头扇区等变量,进而对硬件进行操控。可能有的读者会疑惑,前面不是根据盘块号来得到柱面磁头扇区吗,这里怎么成了扇区号。其实扇区号和盘块号是差不多的,因为有了盘块号就可以得到扇区号,反之有了扇区号也可以得到盘块号,linux0.12中由盘块号得到扇区号是由req->sector=hb->b_blocknr << 1来完成的,这里的sector即是起始扇区,b_blocknr即是盘块号。
  ok,那么我们现在完成了多进程对盘块的基本使用,但是别忘了,操作系统还要让用户更加高效的使用,怎样高效的使用呢,在linux0.12中答案就是电梯算法,限于篇幅,这里不再展开来讲,相信书上和网上都有很多优秀的资料可以查看。

从文件字符流到盘块号

  从上面讨论的结果,我们只需要给os提供盘块号,那么os就可以替我们完成接下来的工作:组织成请求队列,拿出请求,算出柱面磁头扇区。进而磁盘开始工作。但这样还不是我们最终操控磁盘的方式,我们最终是通过文件来最终操控磁盘的。
  我们知道,文件内其实就是一串字符流,那只要知道字符流对应的盘块,我们就可以对磁盘进行操作了,所以现在我们的任务是如何把文件内的字符流映射到某个具体的盘块上。
  如何从字符流映射到盘块呢,可以使用数组,也可以使用链表,但这两种方法都有各自的局限性,linux0.12中是使用索引结构,也就是inode节点,这里的i也就是index的意思。注意i节点分为内存中的i节点和磁盘上的索引节点。前者除了记录后者的全部内容外,也会记录其他的信息如最后访问时间,i节点自身修改时间等,但我们这里的inode专指后者。inode节点中记录了文件的起始盘块号,有了这个,再加上我们知道每个盘块的大小,linux0.12中是2个扇区1024字节,就可以算出某个字符范围对应的盘块号了。
  举个例子,如我们要对test.c中第2099-2200个字符进行删除,首先我们首先要得到test.c对应的i节点结构,怎样得到呢,放到下一节来讲,这里我们先假设已经得到了test.,c的inode结构,那么就可以根据inode中的结构来得到存放相应数据的盘块号。每个盘块1024个字节,那我们想要操作的2099-2200自然在第二个盘块上(从第0个盘块开始),假设第2个逻辑盘块所对应的物理盘块是78,那我们就可以把78和操作数据量201传递给os,接下来的工作就是我们上面讲过的,组织成请求队列,拿出请求,算出柱面磁头扇区。最终磁盘开始工作。
  到现在,我们只需要拿到文件所在的inode,就可以传递给os让磁盘进行工作了,那怎样拿到文件所对应的inode呢,就引出了下面的目录和文件系统。

从目录到文件

  由上面的讲述我们知道,只需要拿到文件对应的inode,就可以让os操作磁盘进行工作了。那怎样拿到文件对应的inode呢?
  想想我们平时操作的文件,都是在某个目录下,看起来像是目录下面存放了多个文件。而实际上,目录也是一个文件,目录只是存放了目录下的文件名和对应的inode号,这个结构被称为目录项(dir_entry),这么一说是不是清晰了很多,只需要得到上级目录的inode,根据inode拿到上级目录的目录项,就可以得到文件的inode并得到盘块号,那上级目录的inode如何得到呢,答案是上上级目录的inode,这样最终会对应到根目录的inode。也就是说,只需要知道根目录的inode,就可以得到任何一个文件的inode,也就可以对任何一个文件进行操作。那么我们知不知道根目录的inode呢,答案是知道的,操作系统会自动为跟目录分配一个盘块并记录下来。那现在的故事就完整了,根据根目录的目录项,一级一级向下查找,直到查找到指定文件并得到指定文件的inode,就可以对os发出指令让磁盘开始工作。

struct dir_entry{unsigned short inode; //i节点号char name[NAME_LEN];    //文件名,长度NAME_LEN=14
};

从open系统调用到柱面磁头扇区

  最后,我们来看一下从open到磁盘工作的大致原理过程。首先open传入所操作文件的所在路径如/a/b/c.c,根据路径,我们首先查找根目录的内容,发现其中a对应的inode是2,接下来去找inode2对应的盘块号,也设为2,那么接下来去读2这个盘块号中存放的内容,得到"b":3,“c”:4,“d”,5,根据匹配,我们拿到b目录对应的inode号,也就是3,根据inode拿到b目录的数据盘块号,也设为3,再去读第3个盘块的内容,设为"c.c":“6”,“d.d”,7,根据匹配,我们拿到c.c对应的Inode号6,那么根据inode6拿到对应的盘块号,也设为6,接下来就可以把盘块号转换为请求结构,放入请求队列,从请求队列中拿出请求,转换为柱面磁头扇区,那么此时磁臂开始移动到指定的磁道,磁盘旋转到指定的扇区,磁头开始工作磁生电/电生磁,最后完成操作!

总结

  本文只是大致讲了操作系统完成磁盘读写的大概原理,一些细节并没有讲到,如磁盘高速缓冲区,高速缓冲是非常有用的,每次读写都要先经过高速缓冲,如果缓冲没有命中才会去进行磁盘操作。原理大概就是这样,实现起来却也比较麻烦,实现到最后,其实也就成为了一个文件系统的结构,如超级块,i节点位图,盘块位图,i节点数组,数据块等等。

下篇代码讲解已更新:【linux0.12】从open系统调用到磁头柱面扇区下篇-----代码讲解

参考资料

哈工大李治军老师视频
《Linux内核完全剖析----基于0.12内核》

【linux0.12】从open系统调用到柱面磁头扇区上篇-----原理讲解相关推荐

  1. 磁盘结构以及磁盘访问时间(柱面 磁头 扇区)

    磁盘容量大,价格低,存取速度快,断电信息后不丢失,可随机存取,因此成为计算机系统中最主要的文件存储设备.磁盘系统的可靠性及其I/O速度的高低,将直接影响到文件操作的效率. 1)盘面 磁盘每一个盘片都有 ...

  2. 操作系统学习:系统调用与Linux0.12初始化详细流程

    本文参考书籍 1.操作系统真相还原 2.Linux内核完全剖析:基于0.12内核 3.x86汇编语言 从实模式到保护模式 4.Linux内核设计的艺术 ps:基于x86硬件的pc系统 系统调用 系统调 ...

  3. 操作系统学习:Linux0.12初始化详细流程-进程1调度与读取硬盘数据

    本文参考书籍 1.操作系统真相还原 2.Linux内核完全剖析:基于0.12内核 3.x86汇编语言 从实模式到保护模式 4.Linux内核设计的艺术 ps:基于x86硬件的pc系统 Linux0.1 ...

  4. 操作系统学习:Linux0.12文件异步IO

    本文参考书籍 1.操作系统真相还原 2.Linux内核完全剖析:基于0.12内核 3.x86汇编语言 从实模式到保护模式 4.Linux内核设计的艺术 ps:基于x86硬件的pc系统 Linux0.1 ...

  5. 操作系统学习:Linux0.12初始化详细流程-进程退出与系统进入怠速

    本文参考书籍 1.操作系统真相还原 2.Linux内核完全剖析:基于0.12内核 3.x86汇编语言 从实模式到保护模式 4.Linux内核设计的艺术 ps:基于x86硬件的pc系统 Linux0.1 ...

  6. 操作系统学习:Linux0.12初始化详细流程-打开文件与加载可执行程序

    本文参考书籍 1.操作系统真相还原 2.Linux内核完全剖析:基于0.12内核 3.x86汇编语言 从实模式到保护模式 4.Linux内核设计的艺术 ps:基于x86硬件的pc系统 Linux0.1 ...

  7. 操作系统学习:Linux0.12初始化详细流程-首个子进程

    本文参考书籍 1.操作系统真相还原 2.Linux内核完全剖析:基于0.12内核 3.x86汇编语言 从实模式到保护模式 4.Linux内核设计的艺术 ps:基于x86硬件的pc系统 Linux0.1 ...

  8. 操作系统学习:Linux0.12初始化详细流程-进程1加载虚拟盘和根文件系统安装

    本文参考书籍 1.操作系统真相还原 2.Linux内核完全剖析:基于0.12内核 3.x86汇编语言 从实模式到保护模式 4.Linux内核设计的艺术 ps:基于x86硬件的pc系统 Linux0.1 ...

  9. 编译运行linux0.12,linux0.12 编译过程

    感谢这篇文章的作者:    http://www.cnblogs.com/strugglesometimes/p/4231359.html 编译是个很蛋疼的事情,本想把linux0.12在bochs上 ...

最新文章

  1. 封装echarts china map geo实现dispatch触发geoSelect事件高亮显示某个省份和城市,并定义复杂样式
  2. Facebook发现:计算机识别系统更青睐识别“有钱人”,准确率高出20%
  3. 设计模式的征途—17.模板方法(Template Method)模式
  4. python解释器是什么-python-解释器在这里做什么
  5. 线性表adt的c语言表达,抽象数据类型定义(ADT)
  6. 多元经验模态分解_【Applied Energy最新原创论文】一个基于多元搜索引擎数据的多尺度油价预测方法...
  7. Ultra96_v2实现交通标示识别
  8. 趣图:你能Get到笑点么?
  9. 浏览器根对象document之字符串属性
  10. 还债速度果然快,罗永浩限高令已再度解除
  11. 大学生买macbookpro合适吗?
  12. 从底层分析python中深拷贝和浅拷贝区别
  13. 【微信小程序开发】 踩坑 抽奖幸运大转盘 完美实战
  14. 冰箱android10,智能手机 篇十:手机冻冰箱总共分几步?AGM推出金嗓子手机H2,超大声音超长待机...
  15. java 事务回滚失败
  16. 如何在服务器上还原数据库文件,SQL Server 使用入门教程(bak文件还原数据库)...
  17. html5gps定位经纬度,html5 定位 获得当前位置的经纬度
  18. 微信公众号实现“一键关注”功能
  19. 人在外省想在老家装监控,在手机上能看,要什么条件和材料?
  20. python期权价格计算器_GitHub - QSCTech-Sange/Options-Calculator: 期权价格计算器——金融工程第二次展示...

热门文章

  1. Unity 之 Playermaker 插件简介 -- 附中文教程和插件分享
  2. 【Linux】网络编程三:TCP通信和UDP通信介绍及代码编写
  3. python constant_Python init.constant方法代码示例
  4. 硬币面值组合(C++)(枚举)
  5. struct timespec 和 struct timeval
  6. 动手搭建安卓开发环境
  7. magmasoft 4.4铸造砂铸模具模流分析视频教程
  8. Obsidian的图片支持HTML本地图片
  9. 移动热点服务的属性此计算机,win10移动热点提示:我们无法设置移动热点怎么办_win10显示无法设置移动热点怎么办...
  10. wordcloud生成词云图(含形状、颜色设置)