操作系统: 设备分配中的数据结构

在多道程序环境下,系统中的设备供所有进程共享。
为防止诸进程对系统资源的无序竞争,特规定系统设备不允许用户自行使用,必须由系统统一分配。
每当进程向系统提出 I/O 请求时,只要是可能和安全的,设备分配程序便按照一定的策略,把设备分配给请求用户(进程)。
在有的系统中,为了确保在 CPU 与设备之间能进行通信,还应分配相应的控制器和通道。

设备分配中的数据结构

—- 在进行设备分配时,通常都需要借助于一些表格的帮助。在表格中记录了相应设备或控制器的状态及对设备或控制器进行控制所需的信息。

在进行设备分配时所需的数据结构(表格)由:
设备控制表(DCT)、
控制器控制表(COCT)、
通道控制表(CHCT)、
系统设备表(SDT)等。

设备控制表(DCT)

系统为每一个设备都配置了一张设备控制表,用于记录本设备的情况:


设备类型:type、
设备标识符:deviceid、
设备状态:等待 / 不等待 忙 / 闲、
指向控制器表的指针、
重复执行次数或时间、
设备队列的队首指针。

设备控制表中,除了有用于指示设备类型的字段 type 和设备标识字段 deviceid 外,还应含有下列字段:

—– 设备队列队首指针。凡因请求本设备而未得到满足的进程,其 PCB 都应按照一定的策略排成一个队列,称该队列为设备请求队列或设备队列。

—– 设备状态。当设备自身正处于使用状态时,应将设备的忙 / 闲标志置“1”。若与该设备相连接的控制器或通道正忙,也不能启动该设备,此时应将设备的等待标志置“1”。

—– 与设备连接的控制器表指针。该指针指向与该设备所连接的控制器的控制表,在设备到主机之间具有多条通路的情况下,一个设备将与多个控制器相连接。此时,在 DCT 中还应设置多个控制器表指针。

—– 重复执行次数。由于外部设备在传送数据时,较易发生数据传送错误,因而在许多系统中,如果发生传送错误,并不立即认为传送失败,而是

令它重新传送,并由系统规定设备在工作中发生错误时应重复执行的次数。

控制器控制表、通道控制表和系统设备表

1)控制器控制表(COCT,Controller control table)。系统为每一个控制器都设置了一张用于记录本控制器情况的控制器控制表。其中记录了:

控制器标识符 -controllerid、控制器状态 - 忙 / 闲、与控制器连接的通道表指针、控制器队列的队首指针、控制器队列的队尾指针。

2)通道控制表(CHCT,Channel control table)。每个通道都配有一张通道控制表。其中记录了:

通道标识符 -channelid、通道状态 - 忙 / 闲、与通道连接的控制器表的指针通道队列的队首指针、通道队列的队尾指针。

3)系统设备表(SDT,System device table)。这是系统范围的数据结构,其中记录了系统中全部设备的情况。每个设备占一个表目,其中包括有

设备类型、设备标识符、设备控制表及设备驱动程序的入口等项。

设备分配时应考虑的因素

设备的固有属性

—- 在分配设备时,首先应考虑与设备分配有关的设备属性。设备的固有属性可分成三种:独占性,指这种设备在一段时间内只允许一个进程独占,即“临界资源”;共享性,指这种设备允许多个进程同时共享;可虚拟性,设备本身虽是独占设备,但经过某种技术处理,可以把它改造成虚拟设备。

根据设备的固有属性应采取不同的分配策略:

1)独占设备。对于独占设备,应采用独享分配策略,即将一个设备分配给某进程后,便由该进程独占,直至该进程完成或释放该设备,然后系统才能再将该设备分配给其他进程使用。缺点:设备得不到充分利用,而且还可能引起死锁。
2)共享设备。对于共享设备,可同时分配给多个进程使用,此时需注意对这些进程访问该设备的先后次序进行合理的调度。
3)可虚拟设备。由于可虚拟设备是指一台物理设备在采用虚拟技术后,可变成多台逻辑上的虚拟设备,因而说,一台可虚拟设备是可共享的设备,

可以将它同时分配给多个进程使用,并对访问该(物理)设备的先后次序进行控制。

设备分配算法

—- 对设备进行分配的算法,与进程调度的算法有些相似之处,但前者相对简单,通常只采用以下两种分配算法:

1)先来先服务。当有多个进程对同一设备提出 I/O 请求时,该算法是根据诸进程对某设备提出请求的先后次序,将这些进程排成一个设备请求队列,设备分配程序总是把设备首先分配给队首进程。
2)优先级高者优先。在进程调度中的这种策略,是优先权高的进程优先获得处理机。如果对这种高优先权进程所提出的 I/O 请求也赋予高优先权,显然有助于这种进程尽快完成。

在利用该算法形成设备队列时,将优先权高的进程排在设备队列前面,而对于优先级相同的 I/O 请求,则按先来先服务原则排队。

设备分配时的安全性

—- 从进程运行的安全性考虑,设备分配有以下两种方式。

1)安全分配方式。
在这种分配方式中,每当进程发出 I/O 请求时,便进入阻塞状态,直到其 I/O 操作完成时才被唤醒。
在采用这种分配策略时,一旦进程已经请求(获得)某种设备(资源)后便阻塞,使该进程不可能再请求其他任何资源,因此,这种分配方式已经摒弃了造成死锁的四个必要条件之一的 "请求和保持" 条件,从而使设备分配是安全的。缺点:进程进展缓慢,即 CPU 与 I/O 设备是串行工作的。

2)不安全分配方式。
在这种分配方式中,进程在发出 I/O 请求后仍继续运行,需要时又发出第二个 I/O 请求、第三个 I/O 请求等。仅当进程所请求的设备已被另一进程占用时,请求进程才进入阻塞状态。这种分配方式的优点是:一个进程可同时操作多个设备,使进程推进迅速。

缺点:分配不安全,因为它可能具备“请求和保持”条件,从而可能造成死锁。因此,在设备分配程序中,还应再增加一个功能,以用于对本次的设备分配是否会发生死锁进行安全性计算,仅当计算结果说明分配是安全的情况下才进行设备分配。

独占设备的分配程序

基本的设备分配程序

—- 当某进程提出 I/O 请求后,系统的设备分配程序可按下述步骤进行设备分配:

1)分配设备

– 首先根据 I/O 请求中的物理设备名,查找系统设备表(SDT),从中找出该设备的 DCT(设备分配表),再根据 DCT 中的设备状态字段,可知

该设备是否正忙。若忙,便将请求 I/O 进程的 PCB 挂在设备队列上;否则,便按照一定的算法来计算本次设备分配的安全性。如果不会导致系统

进入不安全状态,便将设备分配给请求进程;否则,仍将其 PCB 插入设备等待队列。

2)分配控制器

– 在系统把设备分配给请求 I/O 的进程后,再到其 DCT(指向控制器表的指针)中找出与该设备连接的控制器的 COCT(控制器控制表),从 COCT

的状态字段中可知该控制器是否忙碌。若忙,便将请求 I/O 进程的 PCB 挂在该控制器的等待队列上;否则,便将该控制器分配给进程。

3)分配通道

– 通过 COCT 中与控制器连接的通道表指针,找到与该控制器连接的通道的 CHCT(通道控制表),再根据 CHCT 内的状态信息,可知该通道是否

忙碌。若忙,便将请求 I/O 的进程挂在该通道的等待队列上;否则,将该通道分配给进程。

– 只有在设备、控制器和通道三者都分配成功时,这次的设备分配才算成功。然后,便可启动该 I/O 设备进行数据传送。

设备分配程序的改进

—- 仔细研究上述基本的设备分配程序后可以发现:

进程是以物理设备名来提出 I/O 请求的;采用的是单通路的 I/O 系统结构,容易产生“瓶颈”现象。

为此,应从以下两方面对基本的设备分配程序加以改进,以使独占设备的分配程序具有更强的灵活性,并提高分配的成功率。

1)增加设备的独立性

– 为了获得设备的独立性,进程应使用逻辑设备名请求 I/O。这样,系统首先从 SDT 中找出第一个该类设备的 DCT。

若该设备忙,又查找第二个该类设备的 DCT,仅当所有该类设备都忙时,才把进程挂在该类设备的等待队列上;

而只要有一个该类设备可用,系统便进一步计算分配该类设备的安全性。

2)考虑多通路情况

– 为了防止在 I/O 系统中出现“瓶颈”现象(通道不足),通常都采用多通路的 I/O 系统结构。

此时对控制器和通道的分配同样要经过几次反复,即若设备(控制器)所连接的第一个控制器(通道)忙时,应查看其所连接的第二个控制器(通道),

仅当所有的控制器(通道)都忙时,此次的控制器(通道)分配才算失败,才把进程挂在控制器(通道)的等待队列上。

而只要有一个控制器(通道)可用,系统便可将它分配给进程。



代码实现:

  • 结构体声明
struct sdt//系统设备表
{
	char name;//设备名称
	char type;//设备类型
	struct sdt *next;
};

struct block//阻塞设备
{
	char pname;//申请设备进程名
	char ename;//设备名
	struct block *next;
};

struct chct//通道
{
	char name;//通道名称
	int  state;//通道状态
	struct block *next;//通道被占用造成的阻塞队列
};

struct coct//控制器表
{
	char name;//控制器名称
	int state;//控制器状态
	struct chct *chct;//设备通道
	struct block *next;//控制器被占用造成的阻塞队列
};

struct dct//设备控制表
{
	int state; //设备状态
	struct sdt *sdt;//系统设备
	struct coct *coct;//设备控制器
	struct block *next;//设备被占用造成的阻塞队列
};
  • 定义
sdt *s[20];//设备

dct *d[20];//设备控制

coct *co[20];//控制器

chct *ch1,*ch2;//通道1,通道2

block *b;

int e=4;//设备数,初始为4

int c=3;//控制器数,初始为3
  • 初始化
void init()//初始化
{
	for(int i=0;i<4;i++)
	{
		s[i]=new(sdt);
		d[i]=new(dct);
		d[i]->state=0;
		d[i]->sdt=s[i];
		d[i]->next=new(block);
    d[i]->next->next=NULL;
	}
  s[0]->name='k';
	s[1]->name='m';
	s[2]->name='t';
	s[3]->name='p';
	s[0]->type='i';
	s[1]->type='i';
	s[2]->type='o';
	s[3]->type='o';

	for(int i=1;i<4;i++)
	{
		co[i]=new(coct);
		co[i]->state=0;
		co[i]->next=new(block);
		co[i]->next->next=NULL;
	}
  co[1]->name='1';
	co[2]->name='2';
	co[3]->name='3';

	ch1=new (chct);
	ch2=new (chct);
	ch1->name='1';
	ch1->state=0;
	ch1->next=new(block);
	ch1->next->next=NULL;
	ch2->name='2';
	ch2->state=0;
	ch2->next=new(block);
	ch2->next->next=NULL;

	co[1]->chct=ch1;
	co[2]->chct=ch2;
	co[3]->chct=ch2;

	d[0]->coct=co[1];
	d[1]->coct=co[1];
	d[2]->coct=co[2];
	d[3]->coct=co[3];
}

增加设备

void add()
{
	int i;
	char a;
	char b;
	cout<<"设备名称:"<<endl;
	cin>>a;
	cout<<"设备类型:"<<endl;
	cin>>b;
	for(i=0;i<e;i++)
		if(d[i]->sdt->name==a)
			cout<<"设备已存在!"<<endl;
	if(i==e)
	{
	s[e]=new(sdt);
	d[e]=new(dct);
	s[e]->name=a;
	s[e]->type=b;
	d[e]->sdt=s[e];
	d[e]->state=0;
	d[e]->next=new(block);
	d[e]->next->next=NULL;
	e++;
	cout<<"是否新建控制器?(y/n)"<<endl;
	cin>>a;
	if(a=='y')
	{
		char g;
		int flag=0;
		cout<<"请输入新增控制器名称:"<<endl;
		cin>>g;
		if(flag==0)
		{
			for(int k=1;k<=c;k++)
				if(co[k]->name==g)
				{
					flag=1;
					cout<<"该控制器已存在,请重新输入!"<<endl;
			        cin>>g;
				}
		}
		co[c+1]=new(coct);
		co[c+1]->name=g;
		co[c+1]->state=0;
		co[c+1]->next=new(block);
		co[c+1]->next->next=NULL;
		d[e-1]->coct=co[c+1];
		c++;
		cout<<"请选择通道(1/2)"<<endl;
		char f;
		cin>>f;
		if(f=='1')
			co[c]->chct=ch1;
		if(f=='2')
			co[c]->chct=ch2;

		cout<<"设备添加成功!"<<endl;
	}
	else if(a=='n')
    {
		cout<<"当前已存在的控制器有:"<<endl;
		for(int i=1;i<=c;i++)
			cout<<co[i]->name<<endl;
		cout<<"输入选择的控制器名称:"<<endl;
		char cz;
		cin>>cz;
		for(int j=1;j<=c;j++)
		{
			if(cz==co[j]->name)
			{
				cout<<"设备添加成功!"<<endl;
				d[e-1]->coct=co[j];
			}
		}
	}
	}
}

删除设备

void del()
{
	int b;
	block *p;
	cout<<"设备名称:"<<endl;
	char c;
	cin>>c;
	for(int i=0;i<e;i++)
	{
		if(d[i]->sdt->name==c)
		{
			if(d[i]->state==1)
				cout<<"用户进程正在使用设备,无法删除!"<<endl;
			else
			if(d[i]->next->next!=NULL)//设备阻塞队列不空
			{
				p=d[i]->next->next;
				for(;p->ename!=c&&p->next!=NULL;)
					p=p->next;
					cout<<"用户进程"<<p->pname<<"等待使用设备,无法删除!"<<endl;
			}
			else
			if(d[i]->coct->next->next!=NULL)//控制器阻塞队列不空
			{
				p=d[i]->coct->next->next;
				for(;p->ename!=c&&p->next!=NULL;)
					p=p->next;
					cout<<"用户进程"<<p->pname<<"等待使用设备,无法删除!"<<endl;
			}
			else
			if(d[i]->coct->chct->next->next!=NULL)//通道阻塞队列不空
			{
				p=d[i]->coct->chct->next->next;
				for(;p->ename!=c&&p->next!=NULL;)
					p=p->next;
					cout<<"用户进程"<<p->pname<<"等待使用设备,无法删除!"<<endl;
			}
			else
			{
				cout<<"设备删除成功!"<<endl;
				char coc=d[i]->coct->name;
				for(int j=i;j<e;j++)
					d[j]=d[j+1];
				e--;
				cout<<"删除控制器(y/n)?"<<endl;
				char a;
				cin>>a;
				if(a=='y')
				{
					for(b=0;b<e;b++)
						if(d[b]->coct->name==coc)
							cout<<"控制器"<<coc<<"正在使用,无法删除!"<<endl;
					if(b==e-1)
					{
						int j=0;
						while(co[j]->name!=coc)
							j++;
						for(j;j<=c;j++)
							co[j]=co[j+1];
				        c--;
						cout<<"控制器删除成功!"<<endl;
					}
					break;
				}
				else if(a=='n')
					break;
			}
		}
	}
}

请求设备

void require()
{
	block *p;
	char ename,pname;
	cout<<"设备名称:"<<endl;
	cin>>ename;
	cout<<"进程名称:"<<endl;
	cin>>pname;
	for(int i=0;i<e;i++)
	{
		if(d[i]->sdt->name==ename &&d[i]->state==0 &&d[i]->coct->state==0 &&d[i]->coct->chct->state==0)
		{
			d[i]->state=1;
			d[i]->coct->state=1;
			d[i]->coct->chct->state=1;
			cout<<"申请成功!"<<endl;
		}
		else
		if(d[i]->sdt->name==ename&&d[i]->state==1)
		{
			cout<<"设备"<<d[i]->sdt->name<<"被占用,进程阻塞!"<<endl;
			b=new(block);
			b->pname=pname;
			b->ename=ename;
			p=d[i]->next;
			while(p->next!=NULL)
				p=p->next;
			p->next=b;
			b->next=NULL;
		}
		else
		if(d[i]->sdt->name==ename &&d[i]->state==0 &&d[i]->coct->state==1)
		{
			cout<<"控制器"<<d[i]->coct->name<<"被占用,进程阻塞!"<<endl;
			b=new(block);
			b->pname=pname;
			b->ename=ename;
			p=d[i]->coct->next;
			while(p->next!=NULL)
				p=p->next;
			p->next=b;
			b->next=NULL;
		}
		else
		if(d[i]->sdt->name==ename &&d[i]->state==0 &&d[i]->coct->state==0 &&d[i]->coct->chct->state==1)
		{
			cout<<"通道"<<d[i]->coct->chct->name<<"被占用,进程阻塞!"<<endl;
			b=new(block);
			b->pname=pname;
			b->ename=ename;
			p=d[i]->coct->chct->next;
			while(p->next!=NULL)
				p=p->next;
			p->next=b;
			b->next=NULL;
		}
	}
}

回收设备

void callback()
{
	int i,j;
  char n;
	int b;
	cout<<"设备名称:"<<endl;
	cin>>n;
	for(int i=0;i<e;i++)
	{
		if(d[i]->sdt->name==n)
		{
			if(d[i]->state==1)
			{
			    cout<<"设备"<<d[i]->sdt->name<<"回收成功!"<<endl;
			 	d[i]->coct->state=0;
			    d[i]->coct->chct->state=0;
			    d[i]->state=0;
			    if(d[i]->coct->chct->next->next!=NULL)
				{
				    cout<<"进程"<<d[i]->coct->chct->next->next->pname<<"已成功使用"<<d[i]->coct->chct->next->next->ename<<"设备!"<<endl;
				    for(b=0;b<e;b++)
					{
					if(d[i]->coct->chct->next->next->ename==d[b]->sdt->name)
					{
						d[b]->state=1;
						break;
					}
				}
				d[b]->coct->state=1;
				d[i]->coct->chct->state=1;
				block *p;
				p=d[i]->coct->chct->next;
				while(p->next->pname != d[i]->coct->chct->next->next->pname)
					p=p->next;
				p->next = p->next->next;
				break;
			}
			if(d[i]->coct->next->next!=NULL)
			{

				cout<<"进程"<<d[i]->coct->next->next->pname<<"已成功使用"<<d[i]->coct->next->next->ename<<"设备!"<<endl;
				for(b=0;b<e;b++)
				{
					if(d[i]->coct->next->next->ename==d[b]->sdt->name)
						d[b]->state=1;
				}
				d[i]->coct->state=1;
				d[i]->coct->chct->state=1;
				block *q;
				q=d[i]->coct->next;
				while(q->next->pname != d[i]->coct->next->next->pname)
					q=q->next;
				q->next = q->next->next;
				break;
			}
			if(d[i]->next->next!=NULL)
			{
				cout<<"进程"<<d[i]->next->next->pname<<"已成功使用"<<d[i]->next->next->ename<<"设备!"<<endl;
				for(int b=0;b<e;b++)
				{
					if(d[i]->next->next->ename==d[b]->sdt->name)
						d[b]->state=1;
				}

				d[i]->coct->state=1;
				d[i]->coct->chct->state=1;
				block *r;
				r=d[i]->next;
				while(r->next->pname != d[i]->next->next->pname)
					r=r->next;
				r->next = r->next->next;
				break;
			}
			else
			{
				for(int j=0;j<e;j++)
				{
					if(d[j]->coct->chct->next->next!=NULL)
					{
						cout<<"进程"<<d[j]->coct->chct->next->next->pname<<"已成功使用"<<d[j]->coct->chct->next->next->ename<<"设备!"<<endl;
						d[j]->coct->state=1;
						d[j]->coct->chct->state=1;
						block *p;
						p=d[j]->coct->chct->next;
						while(p->next->pname != d[j]->coct->chct->next->pname)
							p=p->next;
						p->next = p->next->next;
						break;
					}
					if(d[j]->coct->next->next!=NULL)
					{
						cout<<"进程"<<d[j]->coct->next->next->pname<<"已成功使用"<<d[j]->coct->next->next->ename<<"设备!"<<endl;
						d[j]->state=1;
						d[j]->coct->state=1;
						d[j]->coct->chct->state=1;
						block *q;
						q=d[j]->coct->next;
						while(q->next->pname != d[j]->coct->next->next->pname)
							q=q->next;
						q->next = q->next->next;
						break;
					}
					if(d[j]->next->next!=NULL)
					{
						cout<<"进程"<<d[j]->next->next->pname<<"已成功使用"<<d[j]->next->next->ename<<"设备!"<<endl;
						d[j]->state=1;
						d[j]->coct->state=1;
						d[j]->coct->chct->state=1;
						block *r;
						r=d[j]->next;
						while(r->next->pname != d[j]->next->next->pname)
							r=r->next;
						r->next = r->next->next;
						break;
					}
				}
				if(j==e)
					cout<<"无阻塞进程"<<endl;
			break;
			}
			}
			else
			{
				cout<<"设备闲置,无须回收!"<<endl;
				break;
			}
		}
	}
	if(i==e)
		cout<<"不存在该设备!"<<endl;
}

磁盘调度算法

//设备管理:磁盘调度
void FCFS(int array[],int m){
    int sum=0,j,i;
    double avg;
    cout<<"\n调度序列:"<<" ";
    for( i=0;i<m;i++)    {
        cout<<array[i]<<" ";
    }
    for(i=0,j=1;j<m;i++,j++)    {
        sum+=abs(array[j]-array[i]);
    }
    avg=sum/(m);
    cout<<"\n移动的总道数: "<<sum<<endl;
    cout<<"平均寻道时间: "<<avg<<endl;
    cout<<endl;
}

最短寻道时间优先算法

// 最短寻道时间优先算法
void ShortPath(int array[],int m)
{     int tmp;
    int k=1;
    int now,l,r,temp;
    int i,j;
    float sum=0,avg=0;
    for(i=0;i<m;i++)
        for(j=i+1;j<m;j++)
        {
            if(array[i]>array[j]) //将磁道号从小到大排序
            {
                temp=array[i];
                array[i]=array[j];
                array[j]=temp;
            }
        }
    cout<<"\n请输入当前的磁道号:"; //输入当前磁道号
    cin>>now;
    tmp=now;
    cout<<"最短寻道时间优先算法(SSTF)\n调度序列:";//输出磁盘调度序列
    if(array[m-1]<=now)  //若被访问的最大的磁道号小于当前的磁道号
        for(int x=m;x>0;x--)
        {
            sum+=now-array[x-1];
            cout<<array[x-1]<<" ";
            now=array[x-1];
        }
    
    else if(now<=array[0])  //若被访问的最小的磁道号大于当前的磁道号
        for(int x=0;x<m;x++)
        {
            sum+=array[x]-now;
            cout<<array[x]<<" ";
            now=array[x];
        }
    //当前的磁道号的值在若所有被访问的磁道号之间
    else{
        while(array[k]<=now) //确定当前磁道在已排的序列中的位置
        {  k++;    }
        l=k-1;
        r=k;
        int count=m;
        while(count>0)
        {
            if(now==array[0])
                while(r<m)
                {
                    cout<<array[r]<<" ";
                    count--;
                    sum+=array[r]-now;
                    now=array[r];
                    r++;
                }
            else if(now==array[m-1])
                while(l>=0)
                {
                    cout<<array[l]<<" ";
                    count--;
                    sum+=now-array[l];
                    now=array[l];
                    l--;
                }
            else
            {
                if((now-array[l])<=(array[r]-now))
                {
                    cout<<array[l]<<" ";
                    count--;
                    sum+=now-array[l];
                    now=array[l];
                    l--;
                }
                else
                {
                    cout<<array[r]<<" ";
                    count--;
                    sum+=array[r]-now;
                    now=array[r];
                    r++;
                }
            }
        }
    }
    
    for(int i=0;i<m;i++)
    {
        if(tmp==array[i])
        {
            m=m-1;
            break;
        }
    }
    avg=sum/(m);
    cout<<endl<<"平均寻道长度:"<<avg<<endl<<endl;//输出平均寻道长度
}

SCAN 算法

//SCAN算法
void Elevator(int array[],int m)  //扫描算法
{     int temp;
    int k=1;
    int now,d,l,r;
    int i,j;
    float sum=0,avg=0;
    for(i=0;i<m;i++)
        for(j=i+1;j<m;j++)
        {
            if(array[i]>array[j]) //将磁道号从小到大排序
            {
                temp=array[i];
                array[i]=array[j];
                array[j]=temp;
            }
        }
    cout<<"\n请输入当前的磁道号:";//输入当前磁道号
    cin>>now;
    cout<<"请选择当前磁头的移动方向:"<<endl<<endl;
    cout<<" 1. 向磁道号增加方向"<<endl;
    cout<<" 0. 向磁道号减小方向"<<endl<<endl;
    cin>>d;          //给出磁头移动方向
    cout<<"扫描算法(SCAN)\n调度序列:";
    if(array[m-1]<=now)   //在序列右方
    {
        for(i=m-1;i>=0;i--)
        { cout<<array[i]<<" ";
            sum+=now-array[i];
            now=array[i];
        }
    }
    else
    {
        if(array[0]>=now) //在序列左方
        {
            for(i=0;i<m;i++)
            {  cout<<array[i]<<" ";
                sum+=array[i]-now;
                now=array[i];
            }
        }
        else  //在序列中间
        {
            while(array[k]<now)  //确定当前磁道在已排的序列中的位置
            {  k++;    }
            l=k-1;
            r=k;
            switch(d)
            {
                case 0:       //先向磁道号减小方向访问
                {
                    while(l>=0)
                    {
                        cout<<array[l]<<" ";
                        sum+=now-array[l];
                        now=array[l];
                        l=l-1;
                    }
                    now=array[0];
                    for(j=r;j<m;j++)
                    {  cout<<array[j]<<" ";
                        sum+=array[j]-now;
                        now=array[j];
                    } break;
                }
                case 1:   //先向磁道号增加方向访问
                {
                    while(r<m)
                    {
                        cout<<array[r]<<" ";
                        sum+=array[r]-now;
                        now=array[r];
                        r=r+1;
                    }
                    now=array[m-1];
                    for(j=l;j>=0;j--)
                    {  cout<<array[j]<<" ";
                        sum+=now-array[j];
                        now=array[j];
                    }break;
                }
                default: cout<<"输入有误"<<endl;
            }
        }
    }
    avg=sum/(m);
    cout<<endl<<"平均寻道长度:"<<avg<<endl<<endl;//输出平均寻道长度
}
  • 功能菜单打印
void version_cipantiaodu() {
    cout<<endl<<endl;
    cout<<"      ┏━━━━━━━━━━━━━━━━━────────────────────━━━━━━┓"<<endl;
    cout<<"      ┃       设 备 管 理:磁 盘 调 度         ┃"<<endl;
    cout<<"      ┠───────────────────────────────────────────┨"<<endl;
    cout<<"      ┃          1.先来先服务                 ┃"<<endl;
    cout<<"      ┃          2.最短寻道时间优先           ┃"<<endl;
    cout<<"      ┃          3.SCAN算法                   ┃"<<endl;
    cout<<"      ┃          0.退出该算法                 ┃"<<endl;
    cout<<"      ┃                               ┃"<<endl;
    cout<<"      ┃       设计时间:20181228             ┃"<<endl;
    cout<<"      ┗━━━━━━━━━━━━━━━━━━━────────────────────━━━━┛"<<endl;
    cout<<endl<<endl;
}
  • 磁盘调度算法, 从外部文件读取 cidao.txt
void cipantiaodu(){
    int chioce;
    int flag=1;
    FILE *fp;
    int cidao[maxsize];
    int i=0,count;
    version_cipantiaodu();
    fp=fopen("cidao.txt","r+");
    if(fp==NULL){
        cout<<"can not find file!"<<endl;
        getchar();
        exit(0);
    }
    while(!feof(fp)){
        fscanf(fp,"%d",&cidao[i]);
        i++;
    }
    count=i-1;
    cout<<"磁盘访问序列:"<<" ";
    for(i=0;i<count;i++){
        printf("%5d",cidao[i]);
    }
    cout<<endl;
    cout<<endl;
  • 选择磁盘调度算法
    while(flag){
        cout<<"请选择:";
        cin>>chioce;
        switch(chioce){
            case 1:
                FCFS(cidao,count);
                break;
            case 2:
                ShortPath(cidao,count);
                break;
            case 3:
                Elevator(cidao,count);
                break;
            case 0:
                flag=0;
                system("clear");
                break;
            default:
                cout<<"选择错误"<<endl<<endl;
        }
    }
    getchar();
}
  • 主菜单打印
void menu()
{
	cout<<"--------------------设备管理---------------------"<<endl;
	cout<<"                 a  添加设备"<<endl; 
	cout<<"                 d  删除设备"<<endl; 
	cout<<"                 r  申请设备"<<endl; 
	cout<<"                 c  回收设备"<<endl;
	cout<<"                 s  设备状态查看"<<endl;
        cout<<"                 p  磁盘调度"<<endl;
	cout<<"                 o  退出程序"<<endl;
	cout<<"-------------------------------------------------"<<endl;
}
  • 设备状态查看
void play()
{
	cout<<"    "<<"设备名称"<<"   "<<"类型"<<"    "<<"控制器"<<"    "<<"通道"<<endl;
	for(int i=0;i<e;i++)
		cout<<"       "<<d[i]->sdt->name<<"        "<<d[i]->sdt->type<<"        "<<d[i]->coct->name<<"       "<<d[i]->coct->chct->name<<endl;

}
  • main 函数, 功能调用
int main()
{
	init();
	menu();
	cout<<"请选择:"<<endl;
	char c;
    cin>>c;
	while(c)
	{
	switch(c)
		{
	    case 'a':
			add();
		    break;
	    case 'd':
			del();
		    break;
	    case 'r':
			require();
		    break;
    	case 'c':
			callback();
     		break;
        case 's':
			play();
        	break;
        case 'p':
            cipantiaodu();
            break;
        case 'o':
			exit(1);
    	default:
	    	cout<<"输入错误! ";
		    break;
		}
    	cout<<"请选择:"<<endl;
        cin>>c;
	}
}

0 打赏
打赏 5 积分后可见