自己动手从零写桌面操作系统GrapeOS系列教程——19.硬盘读写理论知识
学习操作系统原理最好的方法是自己写一个简单的操作系统。
一、硬盘控制器
我们前面已经讲过硬盘控制器是一种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中只有一块硬盘,安装在了主硬盘控制器主盘的位置,下面讲解读写硬盘时的操作步骤。
读硬盘操作步骤
- 读取Status端口,如果该端口位7为0,第6位为1,进入下一步,否则循环当前步骤。
- 向Sector count端口中写入要读入的扇区数。
- 向LBA low、LBA mid、LBA high3个端口依次写入LBA起始扇区号的低24位。
- 向Device端口写入LBA起始扇区号的24~27位,并置第4位为0,第6位为1。
- 向Command端口写入0x20。
- 读取Status端口,如果该端口位7为0,位3为1,则进入下一步,否则循环当前步骤。
- 从Data端口读取数据。如果读1个扇区,则循环读取该端口256次。
写硬盘操作步骤
- 读取Status端口,如果该端口位7为0,第6位为1,进入下一步,否则循环当前步骤。
- 向Sector count端口中写入要写入的扇区数。
- 向LBA low、LBA mid、LBA high3个端口依次写入LBA起始扇区号的低24位。
- 向Device端口写入LBA起始扇区号的24~27位,并置第4位为0,第6位为1。
- 向Command端口写入0x30。
- 读取Status端口,如果该端口位7为0,位3为1,则进入下一步,否则循环当前步骤。
- 向Data端口写入数据。如果写入1个扇区,则循环写入该端口256次。
读硬盘操作和写硬盘操作都是7个步骤,其中只有第5步和第7步不同,其它步骤完全相同。
本讲视频版地址:https://www.bilibili.com/video/BV1854y1M7vx/
配套的代码与资料在:https://gitee.com/jackchengyujia/grapeos-course
GrapeOS操作系统交流QQ群:643474045
自己动手从零写桌面操作系统GrapeOS系列教程——19.硬盘读写理论知识的更多相关文章
- 别人写的一个Bootstrap系列教程
http://www.cnblogs.com/lansy/category/659061.html
- 一个人写的操作系统 - Sparrow OS
一个人写的操作系统 - Sparrow OS 自己写一个操作系统,这是在过去的几年里我一直为之努力的目标,现在终于完成了. 缘起 自己动手写操作系统的动机最初来自于学习Linux遇到的困难. 我是一个 ...
- 自制 os 极简教程1:写一个操作系统有多难
为什么叫极简教程呢?听我慢慢说 不知道正在阅读本文的你,是否是因为想自己动手写一个操作系统.我觉得可能每个程序员都有个操作系统梦,或许是想亲自动手写出来一个,或许是想彻底吃透操作系统的知识.不论是为了 ...
- 【操作系统】关于Linux桌面操作系统
以前是Win+Ubuntu+黑苹果,周末想体验一下deepin,于是简单安装了一下,安装过程很简单,这里不再描述.安装之后,第一次打开系统,确实很惊艳,赏心悦目的操作系统. 之前用Ubuntu时候,C ...
- 盘点|2021年最受欢迎Linux桌面操作系统前十名
镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 阿里云开源镜像站利用云服务上的优势,提供快速.稳定的镜像分发服务.和免费的CDN加速服务.更新频率高,基本上一天一更新,对于Centos/Ubun ...
- 手把手教你从零写一个简单的 VUE
本系列是一个教程,下面贴下目录~1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 今天给大家带来的是实现一个简单的类似 VUE 一样的前端框架,VUE 框架现在应 ...
- 《一步一步写嵌入式操作系统》读书笔记1—Skyeye介绍、安装和HelloWorld
2013-11-14 最近在看<一步一步写嵌入式操作系统>,感觉此书甚好,许多地方讲得很清楚.可操作性强,计划边读边实践边写笔记,希望能够逐步熟悉嵌入式操作系统底层的东西,最终剪裁出一套实 ...
- Python之美[从菜鸟到高手]--一步一步动手给Python写扩展(异常处理和引用计数)
我们将继续一步一步动手给Python写扩展,通过上一篇我们学习了如何写扩展,本篇将介绍一些高级话题,如异常,引用计数问题等.强烈建议先看上一篇,Python之美[从菜鸟到高手]--一步一步动手给Pyt ...
- Zedboard学习(一):移植Ubuntu桌面操作系统 标签: ubuntu移植zedboardFPGA 2017-07-04 21:53 26人阅读
环境准备: 首先,需要的肯定是Ubuntu操作系统.可以在自己的电脑上安装物理机,也可以是虚拟机下运行的.我的是在Vmware下运行的Ubuntu14.04 32位操作系统. 由于zedboard上的 ...
- 27、从零写UVC驱动之分析数据传输(设置ubuntu通过串口打印,指定打印到文件,ubuntu切换root用户)
A. 设置ubuntu让它从串口0输出printk信息a. 设置vmware添加serial port, 使用文件作为串口(在vmware中设置,文件是保存在windows中)b. 启动ubuntu, ...
随机推荐
- 关于C#高阶知识捡漏
高手掠过!仅仅是整理一下 自动属性: C#自动属性可以避免原来这样我们手工声明一个私有成员变量以及编写get/set逻辑 代码如下 //Demo: public class User { publi ...
- Win10家庭版找不到组策略gpedit.msc怎么解决?
链接:https://pan.baidu.com/s/1SoSWCfHwZhD3tV4C7DcirA 提取码:okfm 1.下载文件 2.以管理员身份运行 3.
- 1903021126-申文骏 实验一 19信计java-Markdown排版
项目 内容 课程班级博客链接 19级信计班 作业要求链接 实验一 课程学习目标 大致学会Markdown排版 任务1:在博客园平台注册个人博客账号和加入班级博客 注册了博客园的个人账号,提交了博客申请 ...
- curl下载远程图片到服务器
<?php //curl下载远程图片到服务器 方法 function download($url, $path = 'images/'){ $ch = curl_init(); $names = ...
- echarts 画图报错 this.dom.getContext is not a function
我给 <el-card>绑定了ref,利用$refs获取 echarts实例 const echarts1 = echarts.init(this.$refs.echarts1); 结果 ...
- NPM镜像代理设置
用户目录C:\Users\xxx下建立.npmrc文件,内容如下: registry="https://registry.npm.taobao.org" ELECTRON_MIRR ...
- Flink状态后端的对比及机制
1. Flink状态后端的类型: MemoryStateBackend FsStateBackend RocksDBStateBackend 2. 各状态后端对比: 2.1 MemoryStateBa ...
- [杂谈吐槽]UE国内社区环境
此篇博客是我个人想法,当然也是不争的事实,如果您有意见,那您也是我说那些人其中的一员. --此部分为社区环境差最恶劣的原因-- 国内的虚幻社区环境可以说不能再烂了,虚幻商城和虚幻引擎的蓝图是非常强大的 ...
- 学习JavaScript第一周
三种输出方式,console.log.element.write.alert(): 简单数据类型:数值型.字符串型.布尔类型.undefined.null 复杂数据类型:对象 数据类型的转换:字符串转 ...
- uni-app之返回上⼀个页⾯并传递参数(从页⾯1跳转到页⾯2,然后页⾯2返回页⾯1并且带回参数。 列如新增地址,带回经纬度和地址名称)
uni-app之返回上⼀个页⾯并传递参数 1 reBack: function() { 2 let pages = getCurrentPages(); 3 if (pages.length > ...