学习操作系统原理最好的方法是自己写一个简单的操作系统。


一、硬盘控制器

我们前面已经讲过硬盘控制器是一种I/O接口,CPU通过它就能间接的读写硬盘。硬盘控制器主要有IDE和SATA两种,我们这里只考虑IDE控制器。

电脑里硬盘控制器有2个,一个叫主控制器,另一个叫从控制器。而每个硬盘控制器能连接两个硬盘,一个叫主盘,另一个叫从盘。所以一般一台电脑里最多能安装4个硬盘。

二、硬盘控制器端口

硬盘控制器上的端口很多,下表中只列出我们可能用到的。

I/O端口号 端口用途 端口位数
主控制器 从控制器 读取操作 写入操作
0x1f0 0x170 Data Data 16
0x1f1 0x171 Error Features 8
0x1f2 0x172 Sector count Sector count 8
0x1f3 0x173 LBA low LBA low 8
0x1f4 0x174 LBA mid LBA mid 8
0x1f5 0x175 LBA high LBA high 8
0x1f6 0x176 Device Device 8
0x1f7 0x177 Status Command 8

关于上面这张表,其中的端口号不用记,用的时候翻看一下这里就行。从控制器与主控制器除了端口号不同,其它完全相同,以下我们以主控制器为例讲解。需要注意的是同一个端口在读端口和写端口两种操作下可能用途不一样,比如上表里的0x1f1和0x1f7。

端口0x1f0

首先看第1个端口0x1f0,它是这个表中唯一的16位端口,其它都是8位。从硬盘读取的数据或向硬盘写入的数据都是经过这个端口中转的。之前我们讲过硬盘是按扇区读写的,每个扇区都是512个字节,对硬盘每次读写的数据量都是512字节的整数倍。而这个端口是16位,也就是2个字节。如果你要读取一个扇区的数据,需要从这个端口连续读取256次。同样,写一个扇区,也需要向这个端口连续写入256次。

端口0x1f1

下面来看第二个端口0x1f1,在8个端口中,GrapeOS没有用到这个端口,其它都用到了。虽然没有用到,但还是简单介绍一下。当读操作时,里面保存的是错误信息;当写操作时,曾经需要向该端口写入一些参数,目前已废弃。

端口0x1f2

继续看第三个端口0x1f2,该端口保存的是读取或写入硬盘的扇区数量。该端口是8位端口,取值范围是0~255,但当设置为0时,表示读或写256个扇区。也就是说一次读写操作,最多读写256个扇区。

端口0x1f3~0x1f5

往下3个端口0x1f3、0x1f4、0x1f5是存放读取或写入硬盘时的起始扇区编号。这里用的扇区编号方式叫LBA或LBA28,意思是扇区从0开始编号,用28位二进制数来表示扇区号,最多表示2的28次方个扇区,由于每个扇区512字节,所以最大支持128GB的硬盘。对GrapeOS来说足够了。这里需要注意的是28位是3个半字节,这里的3个端口中,0x1f3存放LBA中的最低1个字节(0 ~ 7位),0x1f4存放中间的那个字节(8 ~ 15位),0x1f5存放高处的那个字节(16 ~ 23位),还剩下最高的半个字节(24 ~ 27位)存放在下个端口0x1f6中。

端口0x1f6

接着看0x1f6端口。这个端口中的低4位存放LBA中的最高4位(24~27位)。第4位0表示主盘,1表示从盘。第6位表示扇区寻址模式,0表示CHS,是一种古老的模式,1表示LBA,我们选LBA。另外第5位和第7位固定为1。参见下表:

bit 内容 说明
7 1 固定为1。
6 MOD 选择寻址模式,0为CHS模式,1为LBA模式。
5 1 固定为1。
4 DEV 选择硬盘驱动器,0为主硬盘,1为从硬盘。
3 [27] LBA地址的第24~27位。
2 [26]
1 [25]
0 [24]

端口0x1f7

我们来看最后一个端口0x1f7,这个端口有两种用途。

如果读取该端口,该端口将作为状态端口,可以获得硬盘的状态信息。如下表所示,该端口8个位中已经有4个位废弃了,有用的是另外4个位。

bit 内容 说明
7 BSY 此位为1表示硬盘正忙,勿扰。
6 DRDY 此位为1表示设备就绪,等待指令。
5 已废弃。
4 已废弃。
3 DRQ 此位为1表示可以从数据端口读写硬盘数据了。
2 已废弃。
1 已废弃。
0 ERR 此位为1表示有错误发生,错误信息见Error寄存器。

如果写入该端口时,该端口将作为命令端口,需要向该端口写入合适的命令。在GrapeOS中只用到两个命令:

  • 读命令:0x20
  • 写命令:0x30

三、硬盘操作方法

在GrapeOS中只有一块硬盘,安装在了主硬盘控制器主盘的位置,下面讲解读写硬盘时的操作步骤。

读硬盘操作步骤

  1. 读取Status端口,如果该端口位7为0,第6位为1,进入下一步,否则循环当前步骤。
  2. 向Sector count端口中写入要读入的扇区数。
  3. 向LBA low、LBA mid、LBA high3个端口依次写入LBA起始扇区号的低24位。
  4. 向Device端口写入LBA起始扇区号的24~27位,并置第4位为0,第6位为1。
  5. 向Command端口写入0x20。
  6. 读取Status端口,如果该端口位7为0,位3为1,则进入下一步,否则循环当前步骤。
  7. 从Data端口读取数据。如果读1个扇区,则循环读取该端口256次。

写硬盘操作步骤

  1. 读取Status端口,如果该端口位7为0,第6位为1,进入下一步,否则循环当前步骤。
  2. 向Sector count端口中写入要写入的扇区数。
  3. 向LBA low、LBA mid、LBA high3个端口依次写入LBA起始扇区号的低24位。
  4. 向Device端口写入LBA起始扇区号的24~27位,并置第4位为0,第6位为1。
  5. 向Command端口写入0x30。
  6. 读取Status端口,如果该端口位7为0,位3为1,则进入下一步,否则循环当前步骤。
  7. 向Data端口写入数据。如果写入1个扇区,则循环写入该端口256次。

读硬盘操作和写硬盘操作都是7个步骤,其中只有第5步和第7步不同,其它步骤完全相同。


本讲视频版地址:https://www.bilibili.com/video/BV1854y1M7vx/

配套的代码与资料在:https://gitee.com/jackchengyujia/grapeos-course

GrapeOS操作系统交流QQ群:643474045

自己动手从零写桌面操作系统GrapeOS系列教程——19.硬盘读写理论知识的更多相关文章

  1. 别人写的一个Bootstrap系列教程

    http://www.cnblogs.com/lansy/category/659061.html

  2. 一个人写的操作系统 - Sparrow OS

    一个人写的操作系统 - Sparrow OS 自己写一个操作系统,这是在过去的几年里我一直为之努力的目标,现在终于完成了. 缘起 自己动手写操作系统的动机最初来自于学习Linux遇到的困难. 我是一个 ...

  3. 自制 os 极简教程1:写一个操作系统有多难

    为什么叫极简教程呢?听我慢慢说 不知道正在阅读本文的你,是否是因为想自己动手写一个操作系统.我觉得可能每个程序员都有个操作系统梦,或许是想亲自动手写出来一个,或许是想彻底吃透操作系统的知识.不论是为了 ...

  4. 【操作系统】关于Linux桌面操作系统

    以前是Win+Ubuntu+黑苹果,周末想体验一下deepin,于是简单安装了一下,安装过程很简单,这里不再描述.安装之后,第一次打开系统,确实很惊艳,赏心悦目的操作系统. 之前用Ubuntu时候,C ...

  5. 盘点|2021年最受欢迎Linux桌面操作系统前十名

    镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 阿里云开源镜像站利用云服务上的优势,提供快速.稳定的镜像分发服务.和免费的CDN加速服务.更新频率高,基本上一天一更新,对于Centos/Ubun ...

  6. 手把手教你从零写一个简单的 VUE

    本系列是一个教程,下面贴下目录~1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 今天给大家带来的是实现一个简单的类似 VUE 一样的前端框架,VUE 框架现在应 ...

  7. 《一步一步写嵌入式操作系统》读书笔记1—Skyeye介绍、安装和HelloWorld

    2013-11-14 最近在看<一步一步写嵌入式操作系统>,感觉此书甚好,许多地方讲得很清楚.可操作性强,计划边读边实践边写笔记,希望能够逐步熟悉嵌入式操作系统底层的东西,最终剪裁出一套实 ...

  8. Python之美[从菜鸟到高手]--一步一步动手给Python写扩展(异常处理和引用计数)

    我们将继续一步一步动手给Python写扩展,通过上一篇我们学习了如何写扩展,本篇将介绍一些高级话题,如异常,引用计数问题等.强烈建议先看上一篇,Python之美[从菜鸟到高手]--一步一步动手给Pyt ...

  9. Zedboard学习(一):移植Ubuntu桌面操作系统 标签: ubuntu移植zedboardFPGA 2017-07-04 21:53 26人阅读

    环境准备: 首先,需要的肯定是Ubuntu操作系统.可以在自己的电脑上安装物理机,也可以是虚拟机下运行的.我的是在Vmware下运行的Ubuntu14.04 32位操作系统. 由于zedboard上的 ...

  10. 27、从零写UVC驱动之分析数据传输(设置ubuntu通过串口打印,指定打印到文件,ubuntu切换root用户)

    A. 设置ubuntu让它从串口0输出printk信息a. 设置vmware添加serial port, 使用文件作为串口(在vmware中设置,文件是保存在windows中)b. 启动ubuntu, ...

随机推荐

  1. NCGROUP遍历成员用的cb

    1 static logical cycelGenerateCb(tag_t tag, void* data) 2 { 3 logical is_group; 4 char name[133]; 5 ...

  2. SpringBoot - 参数校验、统一异常、统一响应

    转载自: https://blog.csdn.net/chaitoudaren/article/details/105610962 前言 本篇主要要介绍的就是controller层的处理,一个完整的后 ...

  3. Leetcode本地阅读器开发--01界面设计三

    这篇文章主要写一下怎样实现定类别查找. 1 void Widget::on_comboBox_currentIndexChanged(int index) 2 { 3 QString sortname ...

  4. 高性能的StampedLock锁

    StampedLock 支持的三种锁模式: 1.ReadWriteLock 支持两种模式:一种是读锁,一种是写锁 2.StampedLock 支持三种模式,分别是:写锁.悲观读锁和乐观读 1)写锁.悲 ...

  5. flask中request请求中各种传参

    from flask import Flask, request from werkzeug.datastructures import FileStorage app = Flask(__name_ ...

  6. oracle转义单引号

    --笔记开始: 每次从表中取数据,然后都要在excel中添加单引号,再粘到查询语句中进行查询比较麻烦. 所以能在查出的结果直接加上单引号是很省时间的 . 这里用到转义. tablename: ep: ...

  7. Delphi书籍大全【阿里云盘】

    「marco cantu的Object Pascal Handbook」等文件 https://www.aliyundrive.com/s/sJtUo8ziUpV 提取码: 5tp6点击链接保存,或者 ...

  8. Callable、Future、FutureTash详解

    Callable.Future.FutureTash详解 Callable与Future是在JAVA的后续版本中引入进来的,Callable类似于Runnable接口,实现Callable接 口的类与 ...

  9. gimp脚本.scm一些心得记录

    gimp的脚本scm一些心得记录 GIMP 2.10 图像处理脚本推荐GIMP使用脚本使得图像处理的功能更加强大,对于一些常见操作可以通过脚本快速实现.GIMP也出来2.10版本了,比前面的2.8相比 ...

  10. 如何服务好B端客户

    核心价值: 2B公司的核心价值在于服务.如何服务好客户,需要的是了解客户,与客户共赢. 一.客户信任度的建立 服务:不是口头说说,是要落地与实践. 对于客户的承诺至关重要,承诺的时间点.承诺的事情要保 ...