行业新闻

您当前的位置:官网首页 > 新闻中心 > 行业新闻 >

硬盘要驱动吗 对于硬盘驱动的理解

来源: 编辑:admin 时间:2020-10-16 12:30

   

第一次看到linux 0.12关于读写硬盘几行代码时分,感觉很隐晦。










我仍是不明白怎样这样就能够读写硬盘了。可是代码到此就完毕了。

一向猎奇程序是怎样操控硬件的,这些指令便是一个个电信号在cpu中活动,怎样就能把硬盘中的数据拿到内存中呢?

正好在同一个学期开设了《核算机组成原理》和《微机原理与接口技能》这两门课程,那个时分才了解到端口的意思,了解到cpu寻址、数据传输的流程。

往端口写了数据和指令,剩余的咱们只能信任硬件制造商的规划和生产能力了,然后静静等候硬件的回应。我记住其时自己疑问了一段时间,苦于没有人来提示这一点,或许会的人感觉这根本不是问题吧。

Linux 0.12其时操作的硬盘是CHS寻址方式,开端利来国际娱乐网扇区编号是1。关于《完成》来说,用bochs自带的东西bximage指令生成的虚拟硬盘是LBA寻址方式的,开端扇区编号是0。CHS方式和LBA方式的端口号和操作方法都相同,只是有一些端口代表的含义不相同了,来看一下LBA寻址方式的端口效果,借用书中的表9.1。

表1  LBA寻址方式的硬盘端口及其效果 

I/O端口

读时

写时  

primary

secondary

1F0H

170H

 Data 

1F1H 

171H 

 Error

 Features

1F2H 

172H 

 Sector count 

1F3H

173H 

 LBA low 

1F4H 

174H 

 LBA mid 

1F5H 

175H 

 LBA high 

1F6H 

176H 

 Device 

1F7H 

177H 

 Status

 Command

3F6H

376H 

 Alternate status

 Device control

其间Device寄存器比较特别,它用来指明寻址方式。来看一下格局。 

表2  Device寄存器各个bit为的含义

Bit位

含义

L

0表明CHS方式,1表明LBA方式

DRV

0表明主盘,1表明从盘

HS3

假如是L=0,CHS方式,那么这四位的值表明磁头号

 

假如L=1,LBA方式,那么这四位的值表明LBA的24到27位

HS2

HS1

HS0

 

从上面的代码能够很清楚的看到怎样读写硬盘,往相应的端口写上咱们要读多少个扇区,读哪个扇区,哪个柱面,哪个磁头,哪个硬盘,然后告知硬盘咱们的需求cmd,读或许写。 

别的,CHS方式下,硬盘扇区编号从1开端编号。LBA方式下,从0开端编号。

咱们怎样知道硬盘的作业做完了没有呢?只能等候硬盘发生中止信号,经过8259A告知cpu,这个中止信号是哪个硬件发生的。

在书中,用的是微内核,一切的进程都给TASK_HD发送读写硬盘的指令,而不是自己调用硬盘驱动中的读写函数。所以中止发生后,只是需求告知TASK_HD这个进程,TASK_HD会把硬盘准备好的数据读到宣布读恳求进程指定的内存方位。

前面说了怎样向硬盘发送指令,让它读写哪些扇区,可是这些参数都是咱们提早核算好的。怎样核算这些参数?咱们又是怎样知道该读写那个扇区呢?

之所以把分区信息的介绍放到读写文件这一末节中,是因为我觉得分区信息和文件相关很大。咱们要读写文件,才需求知道分区信息,假如咱们不需求依照文件方式来读写硬盘,那么知不知道分区信息就无所谓啦,凭咱们的大脑记住要读取的数据在第几个分区,到时分直接汇编操作寄存器就好啦。

那为什么要分区呢?好像不分区把一切的数据都杂糅在一起,电脑也能够正常运转啊。我百度了一下,大概是因为为了把操作体系和数据分隔吧。试想,假如一切的东西和操作体系同处一个空间,那么操作体系溃散了,这个空间的一切数据的记载索引在重新安装操作体系后都会失效,虽然数据自身仍然很正常,可是因为记载索引丢掉,咱们却无法找到他们。假如分区了,那么最多操作体系的地点分区的数据拿不到了,其他分区数据的记载索引还在。

怎样获取分区信息?

在硬盘的0号扇区偏移0x1BE处保存的有一张硬盘主分区表。只需四个表项,也便是说一个硬盘只能记载四个主分区,听说是因为最初IBM以为一个PC上装4个操作体系就够用了。假如想要更多的分区,那么需求在格局化的时分指明一个表项用作扩展分区,扩展分区并不能直接运用,在这个扩展分区里边咱们还要划分出逻辑分区,每一个逻辑分区的开端扇区记载的分区表只能运用两个表项。

关于操作体系而言,每个分区都被作为一个独立的设备对待。

那么书中怎样记载分区信息呢?看一下保存数据的结构体:












书中根设备编号是0x322,能够知道子设备号是0x22,一开端很困惑,这么大的子设备号,莫非要分0x22个分区?或许说体系怎样就知道0x22表明的是根分区呢?

还得再看一段代码





先将设备号减去第一个逻辑设备的编号得到设备号在logical数组的下标。当然,或许这个设备号不是逻辑设备,而是主分区。不要紧,下一步判别p- DEVICE 是不是小于MAX_PRIM,假如小于,阐明是主分区,直接用p- DEVICE在primary数组中取值就能够了。

原来是这样,你想怎样样编号就怎样样编号,只需你自己能找到映射联系就能够了。

获取信息的过程:

device = 0,style = P_PRIMARY

调用获取分区信息函数

假如style == P_ EXTENDED履行第10步

读取设备device的开端扇区,提取0x1BE处的4个表项到part_tbl

令i=0

判别第i个分区表项part_tbl[i]

假如是主分区,记载开端扇区sect_start和扇区数目setcs到相应的primary[i+1]。

假如是扩展分区,记载开端扇区sect_start和扇区数目setcs到相应的primary[i+1],令device += i+1,style = P_ EXTENDED跳到第2步

假如i =4,完毕;不然i++,履行第6步

扩展分区的开端扇区ext_start_sect = primary[device].base,求出该扩展分区的第一个逻辑分区的编号,nr_1st_sub = * NR_SUB_PER_PART,核算该扩展分区第0个逻辑分区的开端地址s= ext_start_sect

令i=0

记载逻辑分区的信息到logical[nr_1st_sub+i]

s = ext_start_sect + part_tbl[1].start_sect

假如i =16,本次递归完毕,返回到第8步;不然i++,履行第12步

感觉文字叙说了解起来或许比较含糊,可是比代码完成起来仍是省劲一些,像读分区开端扇区,一句话带过,知道怎样做就能够了,假如用代码描绘,或许还要牵扯到其他知识点。

其实关于硬盘驱动而言,没有文件这个概念,只需扇区。硬盘驱动能承受的参数便是要读写的开端扇区,读写扇区个数。文件这个概念由上层的文件体系来处理。

这个时分,咱们会想起来inode结构体中有两个记载是i_dev和i_start_sect,这两个元素把上层文件体系和硬盘相关起来了。当咱们要读某某个文件的时分,文件体系告知硬盘驱动读目录区,把文件的inode号找到,再读indoe到内存中,这个时分就有了文件在哪个分区i_dev,数据存放在第i_start_sect号扇区,及之后总共的x800个扇区中,这个i_start_sect的值是相关于分区i_dev为开端偏移的。

知道i_dev和i_start_sect之后,硬盘驱动能够做什么呢?首要将以i_dev分区为开端偏移的i_start_sect转化为相关于整个硬盘。怎样转化呢?上面获取分区信息的时分,每个分区的开端扇区都被记载,咱们找到i_dev的开端扇区,加上i_start_sect便是相关于整个硬盘的了。

这样就把文件读进来了。至于读文件哪一段的内容,其实仍是上层的文件体系来记载处理的,还记住file结构体中有一个元素是pos,这个值便是用来标明要读写的内容在文件中的偏移。将pos/SECT_SIZE再加上上面核算的文件相关于整个硬盘的偏移,便是要读写的某一段数据了。

 所谓块设备的称号或许便是这样由来的吧,一次最少处理的数据是一个扇区。

这样一来,TASK_HD的使命便是很简单了啊,接纳TASK_FS发送的读写恳求,将针关于i_dev设备的i_start_sect转化为相关于整个硬盘的扇区号,再加上pos/SECT_SIZE,然后读写这个扇区交给TASK_FS就什么都不管了。进入下一个循环。

客服