- 前言
- 一、磁盘的介绍
- 二、生磁盘的使用
- 1.IO过程简介
- 2.直接使用磁盘
- 3.盘块号读写磁盘(第一层抽象)
- 4.队列读写磁盘(第二层抽象)
- (1)FCFS磁盘调度算法
- (2)SSTF磁盘调度
- (3)SCAN磁盘调度
- (4)C-SCAN磁盘调度(电梯算法)
- 总结
提示:以下是本篇文章正文内容
一、磁盘的介绍磁盘由一个个盘片组成的磁盘立体结构,一个盘片上下两面都是可读写的
磁盘利用了电流的磁效应,对一些电信号进行磁化,保存在磁盘中,用来表示一些信息。
硬盘又划分为磁头(Heads)、柱面(Cylinder)、扇区(Sector)
磁头(Heads):每张盘面的正反两面各有一个磁头,一个磁头对应一张磁片的一个面。用第几磁头就可以表示数据在哪个磁面
柱面(Cylinder):所有盘面中半径相同的同心磁道构成“柱面”,这一系列的磁道垂直叠在一起,就形成一个柱面的形状
扇区(Sector):将磁道划分为若干个小的区段,就是扇区,每个扇区的容量为512字节,大小本质上是对磁盘数据的传输时间和磁盘的碎片浪费这2项参数的折中
硬盘容量=磁头数×柱面数×扇区数×512字节
结构概况:
磁盘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();
}
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?