專題四 設備管理
一. 名詞解釋
(一)設備按照工作特性分類
存儲設備: 計算機用來存儲信息的設備;
輸入輸出設備: 計算機用來接收來自外部世界信息的設備;
(二)設備按照使用性質來分類
獨佔設備: 在一段時間內,僅允許一個進程獨佔的設備;
共享設備: 由若干進程同時共用的設備;
虛擬設備: 利用某種技術把獨佔設備改造成由多個進程共用的設備;
(三)設備按照數據傳輸的方式來分類
串行設備: 指數據按二進制位一位一位地順序傳送的設備;
並行設備: 指數據按二進制同時通過並行線進行傳送的設備;
(四)設備標識
設備(類型)號: 操作系統爲每類設備規定了一個編號;
設備絕對地址: 系統按照某一種規則位每臺設備分配一個唯一的號碼,用作設備控制器區分和識別設備的代號;
緩衝技術: 目的是緩和設備之間數據傳輸速度不匹配問題的技術;
二. I/O的控制方式
程序查詢方式
工作原理:
– 通過程序不斷循環檢測設備的狀態;
(1)在程序執行的過程中,在進行數據輸入/輸出之前先查詢設備的狀態。
(2)若設備已準備好,則傳送數據;反之程序繼續查詢。
(二)中斷查詢方式
工作原理:
(1)CPU向設備控制器發出一條I/O命令之後,CPU立即返回繼續執行原來的任務;
(2)設備控制器便控制I/O設備進行輸入/輸出;
(3)當設備完成一個字節數據的I/O時,設備控制器產生一箇中斷信號;
(4)CPU檢測到中斷信號之後,進行相應的處理;
(三)直接存儲器(DMA)訪問方式
工作原理:
(1)CPU將DMA命令塊寫入內存,CPU 將命令塊地址寫入DMA控制器的寄存器中,隨後CPU向磁盤控制器發送一個命令,磁盤控制器將數據讀到內部緩衝區;
(2)DMA控制器通過總線發送請求至磁盤控制器,磁盤控制器根據請求將數據以字爲單位通過總線傳送到指定的內存位置,當把數據字寫入內存之後,磁盤控制器通過總線向DMA控制器發送一個回答信號;
(3)DMA相應回答信號做內存地址增加1,減少字節計數;若計數等於0,DMA控制器中斷CPU,傳送完成,若計數大於0,則重複(1)(2);
三. 緩衝技術
引入目的:
(1) 緩解CPU與I/O設備間速度不匹配的問題;
(2) 提高並行性
(3) 減少CPU的中斷頻率.放寬CPU的響應時間;
緩衝技術的類型及使用原則:
單緩衝: 若數據的到達率與離去率相差很大時,則使用單緩衝;
雙緩衝: 信息的輸入和輸出速率相近,則使用雙緩衝;
多緩衝: 若爲陣發性的輸入輸出,則使用多緩衝;
四. SPOOLing系統
SPOOLing的定義 : 多道程序中的一道程序模擬脫機輸入時的外圍控制機的功能,另一道程序模擬脫機輸出時外圍控制機的功能(又稱外圍聯機操作或假脫機操作);
SPOOLing的功能: 是用於將一臺獨佔設備改造成共享設備的一種虛擬技術;
基本組成:
(1)輸入井與輸出井
(2)輸入緩衝區與輸出緩衝區
(3)輸入進程與輸出進程
SPOOLing系統的基本原理:
(1)執行任務之前:預先將程序和數據輸入到輸入井中;
(2)任務運行時:使用數據時,從輸入井中取出/任務運行時:輸出數據時,把數據寫入輸出井;
(3)任務運行完:外設空閒時輸出全部數據和信息;
典型例子:SPOOLing技術如何使一臺打印機虛擬成多臺打印機
(1)由輸出進程在輸出井申請一個磁盤塊區,並將要打印的數據送入其中
(2)輸出進程再爲用戶申請一張空白的用戶請求打印表,並將用戶的打印請求填入表中依次形成打印請求隊列中;
五. 磁盤調度算法
模擬實驗環境: Ubuntu 20.04 visual studio code
FCFS 算法
– 算法設計思想:
磁盤驅動程序每次接受一個請求,並按照請求的順序依次進行
– 模擬實驗源代碼:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
int abs(int value)
{
if(value>=0)
return value;
else
return -value;
}
/*磁道個數*/
int n;
/* 起始位置 */
int begin;
/* 磁道 */
struct Disk
{
int num;//磁道序列
struct Disk* next;
};
struct Quene
{
struct Disk* head;
struct Disk* tail;
};
struct Quene q;
int IsEmpty()
{
if(q.head == NULL)
return 1;
else
return 0;
}
void EnQuene(struct Disk* d)
{
if(q.head == NULL)
{
q.head = d;
q.tail = d;
}
else
{
struct Disk* p = q.tail;
p->next = d;
q.tail = d;
}
}
struct Disk* DeQuene()
{
struct Disk* p = q.head;
q.head = p->next;
p->next = NULL;
return p;
}
void Init()
{
n = rand()%1000;
printf("磁道個數: %d\n",n);
for(int i = 0;i<n;i++)
{
struct Disk* pnew = (struct Disk*)malloc(sizeof(struct Disk));
pnew -> num = rand()%1000;
EnQuene(pnew);
printf("***************** No.%3d 已入隊 *****************\n",pnew->num);
}
printf("\n");
}
double FCFS(int* begin1)
{
begin = *begin1;
double result = 0;
while(!IsEmpty())
{
struct Disk* p = DeQuene();
printf("%3d --> %3d 移動的距離: %3d\n",begin,p->num,abs(p->num - begin));
result = result + (double)(abs(p->num - begin));
begin = p->num;
}
return result;
}
int main()
{
Init();
int b;
printf("Begin = ");
scanf("%d",&b);
printf("\n");
double result = FCFS(&b);
printf("平均尋道時間 = %4f\n",result/n);
return 0;
}
– 模擬實驗(部分)初始值:
– 模擬實驗(部分)過程展示:
– 初始位置與模擬實驗結果:
SSTF 算法
– 算法設計思想:
下一次總是處理與磁頭最近的請求,力求使尋道時間最小化;
– 模擬實驗源代碼:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#define INFINITE 1000
int abs(int value)
{
if(value>=0)
return value;
else
return -value;
}
/*磁道個數*/
int n;
/* 起始位置 */
int begin;
/* 磁道 */
struct Disk
{
int num;//磁道序列
struct Disk* next;
};
struct Disk d;
int IsEmpty()
{
if(d.next == NULL)
return 1;
else
return 0;
}
/* 入"隊"操作 */
void Insert(int num)
{
struct Disk* p;
struct Disk* pnew = (struct Disk*)malloc(sizeof(struct Disk));
pnew -> num = num;
pnew -> next = NULL;
for(p = &d;p->next;p = p -> next);
p -> next = pnew;
}
/* 刪除指定的元素,在本次實驗中經常會與MIN函數連用*/
struct Disk* Delete(struct Disk* d,struct Disk* pos)
{
struct Disk* p1 = d;
struct Disk* p;
for(p = d->next;p;p = p->next,p1 = p1->next)
{
if(p == pos)
{
p1 -> next = p->next;
p -> next = NULL;
return p;
}
}
}
/* 在上升過程中距離最近的磁道的位置 */
struct Disk* MIN()
{
int temp = INFINITE;
struct Disk* pos;
for(struct Disk* p = d.next;p;p = p->next)//尋找當前位置距離最近的磁道
{
if(abs(p->num - begin) <= temp)
{
temp = abs(p->num - begin);
pos = p;
}
}
return pos;
}
/* 初始化 */
void Init()
{
n = rand()%1000;
printf("磁道個數: %d\n",n);
for(int i = 0;i<n;i++)
{
int num = rand()%1000;
Insert(num);
printf("***************** No.%3d 已入隊 *****************\n",num);
}
printf("\n");
}
/* 最短尋道時間優先法 */
double SSTF(int* begin1)
{
begin = *begin1;
double result = 0;
while(!IsEmpty())
{
struct Disk* p = Delete(&d,MIN());
printf("############### %3d F --> %3d F 移動的距離: %3d ###############\n",begin,p->num,abs(begin - p->num));
result = result + (double)(abs(p->num - begin));
begin = p->num;
}
return result;
}
int main()
{
Init();
int b;
printf("Begin = ");
scanf("%d",&b);
printf("\n");
double result = SSTF(&b);
printf("平均尋道時間 = %4f\n",result/n);
return 0;
}
– 模擬實驗初始值:
– 模擬實驗過程展示:
– 初始位置與模擬實驗結果
SCAN 算法
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
#define INFINITE 1000
/*磁道個數*/
int n;
/* 起始位置 */
int begin;
/* 磁道 */
struct Disk
{
int num;//磁道序列
struct Disk* next;
};
/* 下降組 */
struct Disk* Down;
/* 上升組 */
struct Disk* Up;
/* 插入函數,分組依據,判斷與起始位置的大小 */
void Insert(struct Disk* d,int num)
{
struct Disk* p = (struct Disk*)malloc(sizeof(struct Disk));
p-> num = num;
p->next = d->next;
d->next = p;
}
/* 在上升過程中距離最近的磁道的位置 */
struct Disk* MIN()
{
int temp = INFINITE;
struct Disk* pos;
for(struct Disk* p = Up->next;p;p = p->next)
{
if(p->num < temp)
{
temp = p->num;
pos = p;
}
}
return pos;
}
/* 在下降過程中距離最近的磁道的位置 */
struct Disk* MAX()
{
int temp = -1;
struct Disk* pos;
for(struct Disk* p = Down->next;p;p = p->next)
{
if(p->num > temp)
{
temp = p->num;
pos = p;
}
}
return pos;
}
/* 刪除指定的元素,在本次實驗中經常會與MIN,MAX函數連用*/
struct Disk* Delete(struct Disk* d,struct Disk* pos)
{
struct Disk* p1 = d;
struct Disk* p;
for(p = d->next;p;p = p->next,p1 = p1->next)
{
if(p == pos)
{
p1 -> next = p->next;
p -> next = NULL;
return p;
}
}
}
/* 請求訪問磁道隊列 */
struct Quene
{
struct Disk* head;
struct Disk* tail;
};
struct Quene q;
/* 判斷磁道隊列是否爲空 */
int IsEmpty()
{
if(q.head == NULL)
return 1;
else
return 0;
}
/* 入隊操作 */
void EnQuene(struct Disk* d)
{
if(q.head == NULL)
{
q.head = d;
q.tail = d;
}
else
{
struct Disk* p = q.tail;
p->next = d;
q.tail = d;
}
}
/* 初始化 */
void Init()
{
Down = (struct Disk*)malloc(sizeof(struct Disk));
Up = (struct Disk*)malloc(sizeof(struct Disk));
n = rand()%1000;
printf("磁道個數: %d\n",n);
for(int i = 0;i<n;i++)
{
struct Disk* pnew = (struct Disk*)malloc(sizeof(struct Disk));
pnew -> num = rand()%1000;
EnQuene(pnew);
printf("***************** No.%3d 已入隊 *****************\n",pnew->num);
}
printf("\n");
}
/* 判斷磁道組是否爲空 */
int IsEmptyLink(struct Disk* d)
{
if(d->next == NULL)
return 1;
else
return 0;
}
/* 電梯掃描算法 */
double SCAN(int* begin1)
{
begin = *begin1;
double result = 0;
/* 將磁道隊列進行分組*/
for(struct Disk* p1 = q.head;p1;p1 = p1->next)
{
if(p1-> num >= begin) //如果比起始位置要大選擇上升組
Insert(Up,p1->num);
else //如果比起始位置要小選擇下降組
Insert(Down,p1->num);
}
/* 判斷是上升優先還是下降優先,判斷的依據是:隊頭的磁道與起始位置的大小關係 */
if(begin >= q.head->num)//隊頭的磁道不大於起始位置
{
printf("Go Down!\n");
while(!IsEmptyLink(Down))
{
struct Disk* p = Delete(Down,MAX());
printf("***************** %3d -> %3d F 移動的距離: %3d *****************\n",begin,p->num,begin - p->num);
result = result + (double)(begin - p->num);
begin = p->num;
//free(p);
}
if(!IsEmptyLink(Up))
{
printf("Go Up!\n");
printf("%3d ---> %3d 移動的距離: %3d\n",begin,MIN()->num,MIN()->num - begin);
result = result + (double)(MIN()->num - begin);
begin = MIN()->num;
}
while(!IsEmptyLink(Up))
{
struct Disk* p = Delete(Up,MIN());
printf("***************** %3d -> %3d F 移動的距離: %3d *****************\n",begin,p->num,p->num - begin);
result = result + (double)(p->num - begin);
begin = p->num;
//free(p);
}
}
else //隊頭的磁道小於起始位置
{
printf("Go Up!\n");
while(!IsEmptyLink(Up))
{
struct
Disk* p = Delete(Up,MIN());
printf("***************** %3d -> %3d 移動的距離: %3d *****************\n",begin,p->num,p->num - begin);
result = result + (double)(p->num - begin);
begin = p->num;
//free(p);
}
if(!IsEmptyLink(Down))
{
printf("Go Down!\n");
printf("%3d ---> %3dF 移動的距離: %3d \n",begin,MAX()->num,begin - MAX()->num);
result = result + (double)(begin - MAX()->num);
begin = MAX()->num;
}
while(!IsEmptyLink(Down))
{
struct Disk* p = Delete(Down,MAX());
printf("***************** %3d -> %3d 移動的距離: %3d *****************\n",begin,p->num,begin - p->num);
result = result + (double)(begin - p->num);
begin = p->num;
//free(p);
}
}
return result;
}
int main()
{
Init();
int b ;
printf("Begin = ");
scanf("%d",&b);
printf("\n");
double result = SCAN(&b);
printf("平均尋道時間: = %4f\n",result/n);
return 0;
}
– 模擬實驗初始值:
– 模擬實驗過程展示
下降過程:
– 初始位置與模擬實驗結果:
初始
附:參考文獻
[1] 操作系統原理 機械工業出版社 第二版 孟慶昌 張志華
[2] 參考慕課:操作系統 西安交通大學 軟件學院 田麗華(副教授)
[3] 參考慕課:操作系統原理 華中科技大學 軟件學院 蘇曙光(副教授)