操作系统之生磁盘的使用一

磁盘的使用一

什么磁盘

简单来说,就是信息的载体。磁盘利用了电流的磁效应,对一些电信号进行磁化,保存在磁盘中,用来表示一些信息。那么磁盘的结构又是怎样的呢?
在这里插入图片描述

上面这张图是磁盘的示意图。磁盘中有一个概念:盘面。盘面可以理解为磁盘内部中有很多叠加在一起的盘面,磁盘的信息就存储在这些盘面上。
那每张盘面都有什么结构呢?
在这里插入图片描述
从上面这张图可以看出每个盘面上都有磁道、扇区这2个概念。先从磁道说起,每个盘面上有多条圆环,也就是磁道,这些磁道中存储着磁盘的信息。每个磁道上又被分为若干个扇区,磁盘每次的读写数据的操作单位就是这个扇区。每个扇区的大小一般为512字节大小,为啥这个定义呢?本质上是对磁盘数据的传输时间和磁盘的碎片浪费这2项参数的折中。更细致的解释在后面。
现在我们知道了磁盘的基本组成有盘面、磁道、扇区等抽象概念。现在呢我们再考虑一种情况,磁盘是由多个盘片叠加在一起的,由于磁盘每次进行读写的开始都要移动机械的磁臂到对应的盘面、磁道上,这个过程很浪费时间。所以为了提高效率,人们把盘面与磁道抽象成另外2个概念,就是柱面、磁头。
在这里插入图片描述

上图中的cyl就是柱面的意思,就是图中蓝色区域的圆柱体侧面,也称为柱面。上图中的head的范围就是柱面的底部到顶部范围之间。这个一旦确定cyl和head,就确定了哪个盘面和哪个磁道了,这样就可以找到对应的扇区了。为什么把盘面、磁道换成柱面、磁头查找会提高效率呢?根本原因是往往磁盘中盘面很多,每个盘面的承载信息有限,需要移动很多次磁臂才能记录信息。而用柱面的概念的话,就利用了每个盘面磁道的有限性,每次记载数据只需移动很少次的磁臂就可以搞定,提高了读写效率。

使用磁盘

前面介绍了什么是磁盘,那么现在我们知道了磁盘的柱面、磁头、扇区都能概念后,该如何使用磁盘呢?
假如我们要往磁盘的某个扇区写一个字节,那么我们需要知道这个扇区对应的哪个柱面中的哪个磁头。知道了这些参数后,然后把这些参数传到磁盘控制器,磁盘控制器再根据这些参数进行驱动磁盘写数据。下面看一段代码:

// linux-0.11/kernel/blk_drv/hd.c
void do_hd_request(void)
{
	...
	// 前面blabla一大堆,就是要找出dev,nsect,
	// sec,head,cyl,WIN_WRITE,&write_intr这些数据
	// 然后传送这些参数到磁盘控制器
	if (CURRENT->cmd == WRITE) {
		hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
	}
	...
}

上面这段代码就是磁盘读写的请求函数,里面最后调用了hd_out函数,在调用之前传入了柱面号、磁头号、扇区号等核心参数。下面我们看下do_out函数。

static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
		unsigned int head,unsigned int cyl,unsigned int cmd,
		void (*intr_addr)(void))
{
	register int port asm("dx");

	if (drive>1 || head>15)
		panic("Trying to write bad sector");
	if (!controller_ready())
		panic("HD controller not ready");
	do_hd = intr_addr;
	// 这些outb_p接口就是往外设传送数据的
	// 也是cpu中磁盘驱动的核心代码
	outb_p(hd_info[drive].ctl,HD_CMD);
	port=HD_DATA;
	outb_p(hd_info[drive].wpcom>>2,++port);
	outb_p(nsect,++port);
	outb_p(sect,++port);
	outb_p(cyl,++port);
	outb_p(cyl>>8,++port);
	outb_p(0xA0|(drive<<4)|head,++port);
	outb(cmd,++port);
}

上面这段代码就是磁盘驱动的核心代码。从这里不难看出,如果我们想读写磁盘,就传入磁盘的柱面、磁头、扇区、缓冲区等参数后,就可以读写磁盘啦。但是这样呢比较麻烦,在每次读写磁盘的时候。有一种简单的方法,就是把柱面、磁头、扇区包装成一个磁盘块的概念,下面我们来看下磁盘块。

磁盘块封装CHS

通过磁盘块(block)参数怎样计算出柱面号(c)、磁头号(h)、扇区号(s)呢?
我们先来考虑一种情况,假如我们使用block参数读写磁盘,那么每次读写磁盘的block数可能有很多个,为了磁盘读写效率的提升,我们要保证block相邻的磁盘块可以快速读写。如何保证这样的效果呢?如果把相邻的block块读写近似映射成相邻的扇区号读写,那么达到上面的效果了。
所以可以通过这样一个公式来推算chs:
block = c * (heads * sectors) + heads * sectors + s
公式中的heads是一个磁盘的物理磁头总数量;公式中的sectors是一个磁盘盘面的物理扇区总数量。给出block,我们可以逆推出c、h、s这些参数。这样的话我们就可以通过一个block参数进行磁盘读写啦。
还有一个block可以是若干个扇区的,这取决与程序怎样编写。

磁盘的访问时间

磁盘的访问时间 = 写入控制器时间 + 寻道时间 + 旋转时间 + 传输时间
其中寻道时间大约占12ms到8ms。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值