您当前的位置: 首页 > 

风间琉璃•

暂无认证

  • 3浏览

    0关注

    337博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

磁盘的管理(一)

风间琉璃• 发布时间:2021-10-04 19:27:14 ,浏览量:3

文章目录
  • 前言
  • 一、磁盘的介绍
  • 二、生磁盘的使用
    • 1.IO过程简介
    • 2.直接使用磁盘
    • 3.盘块号读写磁盘(第一层抽象)
    • 4.队列读写磁盘(第二层抽象)
        • (1)FCFS磁盘调度算法
        • (2)SSTF磁盘调度
        • (3)SCAN磁盘调度
        • (4)C-SCAN磁盘调度(电梯算法)
  • 总结

提示:以下是本篇文章正文内容

一、磁盘的介绍

磁盘由一个个盘片组成的磁盘立体结构,一个盘片上下两面都是可读写的

磁盘利用了电流的磁效应,对一些电信号进行磁化,保存在磁盘中,用来表示一些信息。

在这里插入图片描述 硬盘又划分为磁头(Heads)、柱面(Cylinder)、扇区(Sector) 在这里插入图片描述 磁头(Heads):每张盘面的正反两面各有一个磁头,一个磁头对应一张磁片的一个面。用第几磁头就可以表示数据在哪个磁面

柱面(Cylinder):所有盘面中半径相同的同心磁道构成“柱面”,这一系列的磁道垂直叠在一起,就形成一个柱面的形状

扇区(Sector):将磁道划分为若干个小的区段,就是扇区,每个扇区的容量为512字节,大小本质上是对磁盘数据的传输时间和磁盘的碎片浪费这2项参数的折中 在这里插入图片描述

硬盘容量=磁头数×柱面数×扇区数×512字节

结构概况: 在这里插入图片描述

二、生磁盘的使用 1.IO过程简介

磁盘I/O过程: 控制器–>寻道–>旋转–>传输 在这里插入图片描述

1.磁头移动到相应的磁道上 2.磁道开始旋转,转到相应的扇区 3.此时再转的时候就是磁生电,磁信号就变成电信号,然后就读取数据 4.读到内存的缓冲区,将这个内存缓冲区修改一个字节 5.然后继续里面再转,此时是电生磁,把字节写到磁道上

移动磁头,移动到对应的磁道上,然后转动磁道,移动到对应的扇区上,一边旋转一边进行磁生电,电生磁,和内存缓冲区进行数据的交互读和写

2.直接使用磁盘

只要往控制器中写柱面、 磁头、 扇区、 缓存位置 在这里插入图片描述假如要往磁盘的某个扇区写一个字节,那么需要知道这个扇区对应的哪个柱面中的哪个磁头把这些参数传到磁盘控制器,磁盘控制器再根据这些参数进行驱动磁盘写数据

(1)磁盘读写的请求函数do_hd_request()


void do_hd_request(void)
{
	..... 
	//前面一些语句就是要得到dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr数据
	// 传递给磁盘控制器
	if (CURRENT->cmd == WRITE) {
		hd_out(dev,nsect,sec,head,cyl,WIN_WRITE,&write_intr);
		for(i=0 ; ibuffer,256);
	} else if (CURRENT->cmd == READ) {
		hd_out(dev,nsect,sec,head,cyl,WIN_READ,&read_intr);
	} else
		panic("unknown hd-command");
}

(2)磁盘驱动的核心代码hd_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(hd_info[drive].ctl,HD_CMD);
	port=HD_DATA; //数据寄存器端口(0x1f0)

	// outb_p接口就是往外设传送数据的
	// cpu中磁盘驱动的核心代码
	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|(driveb_blocknrcmdcmd || ((s1)->cmd==(s2)->cmd && \
((s1)->dev dev || ((s1)->dev == (s2)->dev && \
(s1)->sector sector))))

知道了IN_ORDER()的作用,可以分析一下电梯算法

// linux-0.11/kernel/blk_drv/ll_rw_blk.c
static void add_request(struct blk_dev_struct * dev, struct request * req)
{
	struct request * tmp;

	req->next = NULL;
	cli();   // 开启临界区保护
	if (req->bh)
		req->bh->b_dirt = 0;
	if (!(tmp = dev->current_request)) {
		dev->current_request = req;
		sti();
		(dev->request_fn)();
		return;
	}
	//当符合这两种情况时就跳出循环
	// 并将req插入tmp和next之间
	//(1)当tmp的柱面号小于req的柱面号,且req小于next的柱面号(电梯上升)
	//(2)当tmp的柱面号小于next的柱面号,且req小于next的柱面号(电梯下降)
	// 不管这两种任何一种情况,
	// 下一步磁盘读写都会进入req这个对象上
	//否则就按照原有的,队列进行磁盘读写
	//这样就能更高效的使用磁盘
	for ( ; tmp->next ; tmp=tmp->next)
		if ((IN_ORDER(tmp,req) || 
		    !IN_ORDER(tmp,tmp->next)) &&
		    IN_ORDER(req,tmp->next))
			break;
	req->next=tmp->next;
	tmp->next=req;
	sti();
}

在这里插入图片描述

关注
打赏
1665385461
查看更多评论
立即登录/注册

微信扫码登录

0.0473s