首页 > 编程知识 正文

磁盘分区文件系统类型(【操作系统系列】磁盘基本原理与盘块编号)

时间:2023-05-06 09:34:50 阅读:121240 作者:1070

的基本原理磁盘工作原理

)从CPU中,如果用户想要使用磁盘,CPU会向磁盘设备发送命令,最终通过“out ax,端口号”命令告知磁盘的具体行为详细信息。 )2)从盘(即,盘)在工作完成后通过盘中断传递给CPU,并且CPU在中断处理期间完成后续工作。 例如,将读取到磁盘的内容复制到用户状态的存储器buf中等。 读取/写入磁盘的具体步骤如下。

(1)磁头移动,找到想读的柱面(Cylinder,简称 C)。 由于多个磁头被捆绑在一起移动,每个磁头下面的轨道在各自的盘面上具有相同的位置,所有磁头下面的轨道从上到下组合形成一个“气缸”。 )从气缸中选择具体读写哪个轨道,实际上选择接通哪个**磁头(Head,简称h ) **。 )3)旋转磁盘,将相应轨道中读写的**扇区(Sector,简称s ) **在磁头下拨至一般一个扇区 512 字节。 (4)开始读写,将扇区内容读入内存缓存,或将内存缓存内容导出到该扇区。

使用磁盘的直观方法

让CPU向磁盘控制器发出读写命令。 具体来说,它将向磁盘控制器传递哪个气缸c、哪个磁头h、哪个扇区s、要读写的内存缓存的位置和读写长度。 当然,您需要查看硬件手册以找到与这些信息对应的端口地址。 找到后,CPU用很多out命令导出这些信息就可以了。 磁盘控制器看到这些信息后,会自行执行磁头滑动、磁盘旋转、扇区读写等动作。 voiddo_HD_request(void )//驱动器信息drive //读写长度信息nsect,//读写扇区编号sec //读写磁头编号head, //读写气缸编号cyl //读或写命令cmd ////port_write和port_read中内存缓冲区CURRENT-buffer和磁盘控制器数据寄存器的端口HD 从port_write和port_reead可以容易地看出,这种交换的中心还是out和in指令//#defineport_write(port,buf,nr ) _ ASM _”clite rep; outsw”:3360”d”(port )、“s”) buf、“c”(nr ) )/# define port _ read (port,buf,NR ) __ASM_ )。 rep; insw”:3360”d”(端口)、“d”) buf、“c”(NR )、port_write ) HD_data、CURRENT-buffer、256 ); //或port _ read } void HD _ out (驱动器、nsect、sec、head、cyl、cmd ) { port=HD_DATA; //数据寄存器端口(0x1f0) outb_p ) nsect,端口); outb_p(sect,port ); outb _ p (周期,端口); outb_port(cyl8,port ); outb_p(0xa0| )驱动器4 )|head,port ); outb_p(cmd,port ); }使用原始磁盘(基于块号) L1 )从扇区到磁盘块,直接操作气缸、磁头、扇区要求读写磁盘扇区是不是有点麻烦

因为为了出c、h、s,必须经常在脑子里放入硬盘的结构图。 实际上,您需要了解很多细节,包括磁盘的柱面数、总磁头数和每个磁道可以容纳的扇区数。 否则,c、h和s的值很可能是非法的。 这些细节是,对于典型的APP应用程序编程人员来说,什么样的光盘读写更符合人们的习惯

清除c、h、s的具体细节,让用户觉得有很多扇区排列成一排等待用户使用,用户可以访问第0、1、、10000、10001、个扇区通过地址建立c、h和s扇区地址到扇区号的映射是文件系统第1层抽象的中心任务。 要完成这个映射,地址的设计是最重要的。 寻址方案

很明显,指定磁盘后,0号扇区可以指定位置

0缸(可规定为最外面的缸) 0头;可规定为最上面的头) 0扇区)可规定为盘旋转一周后的扇区)关键问题是1扇区应该位于哪里

是在和0号扇区相同的轨道上相邻的位置吗? 在与0号扇区相邻的下一个气缸上吗? 还是在与0号扇区相邻的下一个磁头上? 必须从提高磁盘读写速度的角度分析扇区编号1的位置

磁盘的读写主要分为三个步骤。 读取和写入的时间也由这三部分组成。 移动磁臂。 也称为寻道。 旋转磁盘; 数据传输。 磁臂移动通常需要10ms左右,寻道时间为10ms; 7200转/分的盘平均旋转半圈,所需时间约为4ms,即旋转时间为4ms; 目前,硬盘的传输速度为每秒十兆字节以上,如下所示

50M/s 为例,传输 1 个扇区 512 个字节需要 0.01ms,即传输时间为 0.01ms。即:对比这三个数字一目了然,读写磁盘的主要时间花费是寻道上。 另一方面,一旦将所有扇区“排成一排”,变成一个线性序列 0、1、2、···进行读写时。我们通常会读写扇区号连续的多个扇区 因为在给一个文件分配扇区空间时,比如文件需要 10 个扇区,通常我们会找出一段扇区号连续的磁盘空间进行分配,比如从 1000—1009 的 10 个扇区。再根据局部性原理,我们在一段时间内通常会读写文件中一个连续区域,两个连续导致的结果就是在一段时间内通常要读写扇区号连续的多个扇区。所以,在读写完 0 号扇区以后,很可能去读写 1 号扇区。 如果读写完 0 号扇区以后,马上去读写 1 号扇区,最省寻道时间和旋转时间的显然是”是和 0 号扇区在同一个磁道上且相邻的位置“ 因为这种情况下不用寻道也不用旋转(在磁盘读写的时候,要滑过整个扇区,因为要有相对运动才能将磁信号变成电信号)

s e c t o r = C × ( H e a d s × S e c t o r s ) + H × S e c t o r s + S sector = C × (Heads × Sectors) + H × Sectors + S sector=C×(Heads×Sectors)+H×Sectors+S

sector 是扇区号Heads 是磁盘的磁头数量。Sectors 是每个磁道的扇区数

计算C、H、S

C = s e c t o r / S e c t o r s / H e a d s C = sector/Sectors/Heads C=sector/Sectors/Heads

H = s e c t o r / S e c t o r s H = sector/Sectors%Heads H=sector/Sectors

S = s e c t o r % S e c t o r s S = sector%Sectors S=sector%Sectors

磁盘块

扇区号连续的多个扇区就是一个磁盘块 引入磁盘块以后用户读写磁盘的基本单位就不再是扇区,而是磁盘块了。用磁盘块将扇区概念隐藏起来,是文件系统的第一层抽象. 为什么每次读写要读写多个连续扇区而不是一个扇区呢 因为数据传输时间和寻道/旋转时间相比要小得多,所以寻道、旋转一次读写 K 个扇区的策略比只读写 1 个扇区的策略,其磁盘读写速度的提高接近于 K倍。所以抽象出磁盘块以后,磁盘读写速度会有非常显著提高。具体的说,用了 14ms+0.01ms 读写了一个扇区,磁盘的读写速度是 0.5K/14.01ms;但如果用14ms+0.1ms 读写了十个扇区,其中 0.1ms 是传输 10 个扇区数据的时间,磁盘的读写速度就变成为 5K/14.1ms,速度提高了 9.93 倍。 磁盘块作为磁盘读写的基本单位也有缺点:造成磁盘空间的浪费 这是显然的,以 1M 作为单位进行磁盘分配,一个文件平均会造成 0.5M 的空间浪费,即该文件的最后一个盘块即使没有用满也不能分配给别的文件使用(不然读这个文件会读到其他文件的内容)。但是现在的磁盘容量通常都很大,相比来说,读写速度要重要的多。

计算 C、H、S:用盘块号 blocknr→ sector → C、H、S

s e c t o r = b l o c k n r × b l o c k s i z e sector = blocknr × blocksize sector=blocknr×blocksize

其中 blocksize 是描述磁盘块大小的一个参数,这是操作系统可以调整的一个参数。

一旦算出扇区号以后,再用上面给出的公式计算出 C、H、S,然后 CPU 就可以发出 out 命令了。

static void make_request(){ // requset 中的核心信息就是用户要读写的扇区号 sector,该信息是根据用户提供的盘块号 blocknr 计算得出的 struct requset *req; req = request+NR_REQUEST; req->sector=bh->b_blocknr«1; add_request(major+blk_dev,req);}// do_hd_request 函数会使用汇编指令 divl实现从 sector 到 C、H、S 的计算void do_hd_request(void){ unsigned int block=CURRENT->sector; __asm__(“divl %4”:”=a”(block),”=d”(sec):”0”(block),“1”(0),” // hd_info[dev].sect 就是公式中 Sectors // 在系统启动时调用 BIOS 中断获得并初始化到 hd_info 数据结构中的 r”(hd_info[dev].sect)); __asm__(“divl %4”:”=a”(cyl),”=d”(head):”0”(block),“1”(0),” // hd_info[dev].head 是公式中的 Heads // 在系统启动时调用 BIOS 中断获得并初始化到 hd_info 数据结构中的 r”(hd_info[dev].head)); hd_out(dev,nsect,sec,head,cyl,WRITE);}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。