[操作系统]设备分配中的数据结构:设备控制表(DCT)、控制器控制表(COCT)、通道控制。。。
在多道程序环境下,系统中的设备供所有进程共享。为防⽌诸进程对系统资源的⽆序竞争,特规定系统设备不允许⽤户⾃⾏使⽤,必须由系统统⼀分配。每当进程向系统提出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++)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论