操作系统实验报告18:硬盘柱面访问调度算法
操作系統(tǒng)實(shí)驗(yàn)報(bào)告18
實(shí)驗(yàn)內(nèi)容
- 實(shí)驗(yàn)內(nèi)容:硬盤調(diào)度。
- 編寫 C 程序模擬實(shí)現(xiàn)課件 Lecture25 中的硬盤柱面訪問調(diào)度算法
包括 FCFS、SSTF、SCAN、C-SCAN、LOOK、C-LOOK,并設(shè)計(jì)輸入用例驗(yàn)證結(jié)果。
- 編寫 C 程序模擬實(shí)現(xiàn)課件 Lecture25 中的硬盤柱面訪問調(diào)度算法
實(shí)驗(yàn)環(huán)境
- 架構(gòu):Intel x86_64 (虛擬機(jī))
- 操作系統(tǒng):Ubuntu 20.04
- 匯編器:gas (GNU Assembler) in AT&T mode
- 編譯器:gcc
技術(shù)日志
實(shí)驗(yàn)內(nèi)容原理
- 磁盤
- 磁盤或硬盤為現(xiàn)代計(jì)算機(jī)系統(tǒng)提供大量外存。在概念上磁盤比較簡(jiǎn)單。每個(gè)盤片為平的圓狀,如同CD一樣。盤片的兩面都涂著磁質(zhì)材料。通過在盤片上進(jìn)行磁性記錄可以保存信息。
- 讀寫磁頭“飛行”在一個(gè)盤片的表面上方。磁頭附著在磁臂上,磁臂將所有磁頭作為一個(gè)整體而一起移動(dòng)。盤片的表面邏輯地分成圓形磁道,再細(xì)分為扇區(qū)。同一磁臂位置的磁道集合形成了柱面。每個(gè)磁盤驅(qū)動(dòng)器有數(shù)千個(gè)同心柱面,而每個(gè)磁道可能包括數(shù)百個(gè)扇區(qū)。常見磁盤驅(qū)動(dòng)器的存儲(chǔ)容量按GB來計(jì)算。
- 移動(dòng)磁頭的磁盤裝置圖:
- 當(dāng)使用磁盤時(shí),驅(qū)動(dòng)器電機(jī)高速旋轉(zhuǎn)磁盤。大多數(shù)驅(qū)動(dòng)器每秒旋轉(zhuǎn)60~250次,按每分鐘轉(zhuǎn)數(shù)(RPM)來計(jì)。普通驅(qū)動(dòng)器的轉(zhuǎn)速為5400、7200、10000和15000RPM。磁盤速度有兩部分。
- 傳輸速率是在驅(qū)動(dòng)器和計(jì)算機(jī)之間的數(shù)據(jù)流的速率。
- 定位時(shí)間或隨機(jī)訪問時(shí)間包括兩部分:
- 尋道時(shí)間(移動(dòng)磁臂到所要柱面的所需時(shí)間)
- 旋轉(zhuǎn)延遲(旋轉(zhuǎn)磁臂到所要扇區(qū)的所需時(shí)間)
- 典型的磁盤可以按每秒數(shù)兆字節(jié)的速率來傳輸,并且尋道時(shí)間和旋轉(zhuǎn)延遲為數(shù)毫秒。
- 磁盤或硬盤為現(xiàn)代計(jì)算機(jī)系統(tǒng)提供大量外存。在概念上磁盤比較簡(jiǎn)單。每個(gè)盤片為平的圓狀,如同CD一樣。盤片的兩面都涂著磁質(zhì)材料。通過在盤片上進(jìn)行磁性記錄可以保存信息。
- 磁盤調(diào)度
- 操作系統(tǒng)的職責(zé)之一是有效使用硬件。
- 對(duì)于磁盤驅(qū)動(dòng)器,滿足這個(gè)要求具有較快的訪問速度和較寬的磁盤帶寬。
- 對(duì)于磁盤,訪問時(shí)間包括兩個(gè)主要部分
- 尋道時(shí)間是磁臂移動(dòng)磁頭到包含目標(biāo)扇區(qū)的柱面的時(shí)間。
- 旋轉(zhuǎn)延遲是磁盤旋轉(zhuǎn)目標(biāo)扇區(qū)到磁頭下的額外時(shí)間。
- 假設(shè)尋道時(shí)間約等價(jià)于尋道距離
- 磁盤帶寬是傳輸字節(jié)的總數(shù)除以從服務(wù)請(qǐng)求開始到最后傳遞結(jié)束時(shí)的總時(shí)間。
- 通過管理磁盤IO請(qǐng)求的處理次序,可以改善訪問時(shí)間和帶寬。
- 每當(dāng)進(jìn)程需要進(jìn)行磁盤I/O操作時(shí),它就向操作系統(tǒng)發(fā)出一個(gè)系統(tǒng)調(diào)用。這個(gè)請(qǐng)求需要些信息
- 這個(gè)操作是輸入還是輸出
- 傳輸?shù)拇疟P地址是什么
- 傳輸?shù)膬?nèi)存地址是什么
- 傳輸?shù)纳葏^(qū)數(shù)是多少
- 如果所需的磁盤驅(qū)動(dòng)器和控制器空閑,則立即處理請(qǐng)求。如果磁盤驅(qū)動(dòng)器或控制器忙,則任何新的服務(wù)請(qǐng)求都會(huì)添加磁盤驅(qū)動(dòng)器的待處理請(qǐng)求隊(duì)列。對(duì)于具有多個(gè)進(jìn)程的一個(gè)多道程序系統(tǒng),磁盤隊(duì)列可能有多個(gè)待處理的請(qǐng)求。因此,當(dāng)一個(gè)請(qǐng)求完成時(shí),操作系統(tǒng)可以使用磁盤調(diào)度算法選擇哪個(gè)待處理的請(qǐng)求服務(wù)。
- 操作系統(tǒng)的職責(zé)之一是有效使用硬件。
- 磁盤調(diào)度算法
- FCFS先來先服務(wù)調(diào)度算法
- 按順序處理I/O請(qǐng)求
- 對(duì)所有進(jìn)程都是公平的
- 如果有許多進(jìn)程/請(qǐng)求,則在性能上接近隨機(jī)調(diào)度
- 在全局上會(huì)有之字形效應(yīng),通常不提供最快的服務(wù)
- SSTF最短尋道時(shí)間優(yōu)先調(diào)度算法
- SSTF從當(dāng)前磁頭位置選擇具有最小尋道時(shí)間的請(qǐng)求。
- 也稱為最短尋道距離優(yōu)先(SSDF),因?yàn)橛?jì)算距離更加容易。
- 是一種最近鄰法。
- 這個(gè)算法更加偏重于處理中間的柱面請(qǐng)求。
- SSTF調(diào)度是SJF調(diào)度的一種形式;可能會(huì)導(dǎo)致某些請(qǐng)求無法滿足。
- SSTF從當(dāng)前磁頭位置選擇具有最小尋道時(shí)間的請(qǐng)求。
- SCAN掃描算法
- 磁臂從磁盤的一端開始,向另一端移動(dòng);在移過每個(gè)柱面時(shí),處理請(qǐng)求。當(dāng)?shù)竭_(dá)磁盤的另一端時(shí),磁頭移動(dòng)方向反轉(zhuǎn),并繼續(xù)處理。磁頭連續(xù)來回掃描磁盤。
- C-SCAN循環(huán)掃描算法
- 是SCAN的一個(gè)變種,以提供更均勻的等待時(shí)間。
- 像SCAN一樣,C-SCAN移動(dòng)磁頭從磁盤一端到磁盤另一端,并且處理行程上的請(qǐng)求。然而,當(dāng)磁頭到達(dá)另一端時(shí),它立即返回到磁盤的開頭,而并不處理任何回程上的請(qǐng)求
- LOOK調(diào)度算法和C-LOOK算法
- SCAN和C-SCAN在磁盤的整個(gè)寬度內(nèi)移動(dòng)磁臂。實(shí)際上,這兩種算法通常都不是按這種方式實(shí)施的。更常見的是,磁臂只需移到一個(gè)方向的最遠(yuǎn)請(qǐng)求為止。遵循這種模式的SCAN算法和C-SCAN算法分別稱為L(zhǎng)OOK和 C-LOOK調(diào)度,因?yàn)樗鼈冊(cè)谙蛱囟ǚ较蛞苿?dòng)時(shí)查看是否會(huì)有請(qǐng)求。
- FCFS先來先服務(wù)調(diào)度算法
設(shè)計(jì)報(bào)告
代碼設(shè)計(jì)
//HDD_scheduling.c文件 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h>#define CYLINDER_REQ_NUM 8 // I/O請(qǐng)求塊的柱面數(shù)目 #define CYLINDER_NUM 200 // 總的柱面數(shù)目// 取一個(gè)數(shù)的絕對(duì)值 int abs_int(int num);// 硬盤柱面訪問調(diào)度算法 void FCFS(int *cylinders, int *cylinder_req, int cylinder_head); void SSTF(int *cylinders, int *cylinder_req, int cylinder_head); void SCAN(int *cylinders, int *cylinder_req, int cylinder_head, int head_dir); void C_SCAN(int *cylinders, int *cylinder_req, int cylinder_head, int head_dir); void LOOK(int *cylinders, int *cylinder_req, int cylinder_head, int head_dir); void C_LOOK(int *cylinders, int *cylinder_req, int cylinder_head, int head_dir);// 找到距離當(dāng)前磁頭最近的請(qǐng)求處理的柱面 int find_cylinder_min_seek_dis(int *cylinders, int cylinder_head); // 將I/O請(qǐng)求塊的柱面在硬盤上設(shè)置相應(yīng)的請(qǐng)求 void set_cylinders(int *cylinders, int *cylinder_req); // 打印I/O請(qǐng)求塊的柱面的信息 void print_cylinder_req(int *cylinder_req); // 打印開始時(shí)磁頭掃描方向 void print_head_dir(int head_dir);// 取一個(gè)數(shù)的絕對(duì)值 int abs_int(int num) {if (num >= 0) {return num;} else {return -num;} }// 先來先服務(wù)調(diào)度算法 void FCFS(int *cylinders, int *cylinder_req, int cylinder_head) {printf("\n--------------------------------------------------------\n");printf("HDD Scheduling Algorithm: FCFS\n");print_cylinder_req(cylinder_req);printf("\n");// 初始化硬盤柱面,設(shè)置相應(yīng)柱面請(qǐng)求處理memset(cylinders, 0, CYLINDER_NUM * sizeof(int));set_cylinders(cylinders, cylinder_req);int head_move_sum = 0;printf("head's movement: ");// 打印一開始磁頭處于柱面位置if (cylinders[cylinder_head] == 0) {printf("%d ", cylinder_head);}for(int i = 0; i < CYLINDER_REQ_NUM; ++i) {int cylinder_id = cylinder_req[i];// 直接按照柱面請(qǐng)求順序處理請(qǐng)求柱面printf("%d ", cylinder_id);// 處理后的柱面在硬盤上的請(qǐng)求數(shù)減一cylinders[cylinder_id]--;// 將磁頭移動(dòng)距離加到磁頭移動(dòng)總距離中head_move_sum += abs_int(cylinder_head - cylinder_id);// 磁頭位置為處理完的柱面位置cylinder_head = cylinder_id;}printf("\nThe total movement of head = %d cylinders\n", head_move_sum);printf("--------------------------------------------------------\n"); }// 最短尋道時(shí)間優(yōu)先調(diào)度算法 void SSTF(int *cylinders, int *cylinder_req, int cylinder_head) {printf("\n--------------------------------------------------------\n");printf("HDD Scheduling Algorithm: SSTF\n");print_cylinder_req(cylinder_req);printf("\n");// 初始化硬盤柱面,設(shè)置相應(yīng)柱面請(qǐng)求處理memset(cylinders, 0, CYLINDER_NUM * sizeof(int));set_cylinders(cylinders, cylinder_req);int head_move_sum = 0;printf("head's movement: ");// 打印一開始磁頭處于柱面位置if (cylinders[cylinder_head] == 0) {printf("%d ", cylinder_head);}for(int i = 0; i < CYLINDER_REQ_NUM; ++i) {int cylinder_id = find_cylinder_min_seek_dis(cylinders, cylinder_head);// 直接按照柱面請(qǐng)求順序處理請(qǐng)求柱面printf("%d ", cylinder_id);// 處理后的柱面在硬盤上的請(qǐng)求數(shù)減一cylinders[cylinder_id]--;// 將磁頭移動(dòng)距離加到磁頭移動(dòng)總距離中head_move_sum += abs_int(cylinder_head - cylinder_id);// 磁頭位置為處理完的柱面位置cylinder_head = cylinder_id;}printf("\nThe total movement of head = %d cylinders\n", head_move_sum);printf("--------------------------------------------------------\n"); }// 掃描調(diào)度算法 void SCAN(int *cylinders, int *cylinder_req, int cylinder_head, int head_dir) {printf("\n--------------------------------------------------------\n");printf("HDD Scheduling Algorithm: SCAN\n");print_cylinder_req(cylinder_req);print_head_dir(head_dir);printf("\n");// 初始化硬盤柱面,設(shè)置相應(yīng)柱面請(qǐng)求處理memset(cylinders, 0, CYLINDER_NUM * sizeof(int));set_cylinders(cylinders, cylinder_req);int pre_cylinder_head = cylinder_head;int head_move_sum = 0;printf("head's movement: ");// 打印一開始磁頭處于柱面位置if (cylinders[cylinder_head] == 0) {printf("%d ", cylinder_head);}// 向一個(gè)方向掃描直到盡頭while (cylinder_head >= 0 && cylinder_head < CYLINDER_NUM) {// 如果磁頭在請(qǐng)求處理的柱面上while (cylinders[cylinder_head] > 0) {printf("%d ", cylinder_head);// 將磁頭移動(dòng)距離加到磁頭移動(dòng)總距離中head_move_sum += abs_int(cylinder_head - pre_cylinder_head);// 更新磁頭上一次處在的位置pre_cylinder_head = cylinder_head;// 處理后的柱面在硬盤上的請(qǐng)求數(shù)減一cylinders[cylinder_head]--;}// 如果head_dir為0,向朝0的方向掃描if (head_dir == 0) {cylinder_head--;} else {// 如果head_dir為1,向朝CYLINDER_NUM的方向掃描cylinder_head++;}}// 令磁頭到達(dá)一側(cè)盡頭if (cylinder_head == -1) {cylinder_head++;}if (cylinder_head == CYLINDER_NUM) {cylinder_head--;}if (pre_cylinder_head != cylinder_head) {printf("%d ", cylinder_head);head_move_sum += abs_int(cylinder_head - pre_cylinder_head);pre_cylinder_head = cylinder_head;}// 調(diào)轉(zhuǎn)掃描方向if (head_dir == 0) {head_dir = 1;} else {head_dir = 0;}// 向另一個(gè)方向繼續(xù)掃描while (cylinder_head >= 0 && cylinder_head < CYLINDER_NUM) {while (cylinders[cylinder_head] > 0) {printf("%d ", cylinder_head);head_move_sum += abs_int(cylinder_head - pre_cylinder_head);pre_cylinder_head = cylinder_head;cylinders[cylinder_head]--;}if (head_dir == 0) {cylinder_head--;} else {cylinder_head++;}}printf("\nThe total movement of head = %d cylinders\n", head_move_sum);printf("--------------------------------------------------------\n"); }// 循環(huán)掃描調(diào)度算法 void C_SCAN(int *cylinders, int *cylinder_req, int cylinder_head, int head_dir) {printf("\n--------------------------------------------------------\n");printf("HDD Scheduling Algorithm: C-SCAN\n");print_cylinder_req(cylinder_req);print_head_dir(head_dir);printf("\n");// 初始化硬盤柱面,設(shè)置相應(yīng)柱面請(qǐng)求處理memset(cylinders, 0, CYLINDER_NUM * sizeof(int));set_cylinders(cylinders, cylinder_req);int pre_cylinder_head = cylinder_head;int head_move_sum = 0;printf("head's movement: ");// 打印一開始磁頭處于柱面位置if (cylinders[cylinder_head] == 0) {printf("%d ", cylinder_head);}// 向一個(gè)方向掃描直到盡頭while (cylinder_head >= 0 && cylinder_head < CYLINDER_NUM) {// 如果磁頭在請(qǐng)求處理的柱面上while (cylinders[cylinder_head] > 0) {printf("%d ", cylinder_head);// 將磁頭移動(dòng)距離加到磁頭移動(dòng)總距離中head_move_sum += abs_int(cylinder_head - pre_cylinder_head);// 更新磁頭上一次處在的位置pre_cylinder_head = cylinder_head;// 處理后的柱面在硬盤上的請(qǐng)求數(shù)減一cylinders[cylinder_head]--;}// 如果head_dir為0,向朝0的方向掃描if (head_dir == 0) {cylinder_head--;} else {// 如果head_dir為1,向朝CYLINDER_NUM的方向掃描cylinder_head++;}}// 令磁頭到達(dá)一側(cè)盡頭if (cylinder_head == -1) {cylinder_head++;}if (cylinder_head == CYLINDER_NUM) {cylinder_head--;}if (pre_cylinder_head != cylinder_head) {printf("%d ", cylinder_head);head_move_sum += abs_int(cylinder_head - pre_cylinder_head);pre_cylinder_head = cylinder_head;}// 令磁頭直接到達(dá)另一側(cè)盡頭if (cylinder_head == 0) {cylinder_head = CYLINDER_NUM - 1;} else if (cylinder_head == CYLINDER_NUM - 1) {cylinder_head = 0;}pre_cylinder_head = cylinder_head;head_move_sum += CYLINDER_NUM - 1;if (cylinders[cylinder_head] == 0) {printf("%d ", cylinder_head);}// 向同一方向繼續(xù)掃描while (cylinder_head >= 0 && cylinder_head < CYLINDER_NUM) {while (cylinders[cylinder_head] > 0) {printf("%d ", cylinder_head);head_move_sum += abs_int(cylinder_head - pre_cylinder_head);pre_cylinder_head = cylinder_head;cylinders[cylinder_head]--;}if (head_dir == 0) {cylinder_head--;} else {cylinder_head++;}}printf("\nThe total movement of head = %d cylinders\n", head_move_sum);printf("--------------------------------------------------------\n"); }// LOOK電梯調(diào)度算法 void LOOK(int *cylinders, int *cylinder_req, int cylinder_head, int head_dir) {printf("\n--------------------------------------------------------\n");printf("HDD Scheduling Algorithm: LOOK\n");print_cylinder_req(cylinder_req);print_head_dir(head_dir);printf("\n");// 初始化硬盤柱面,設(shè)置相應(yīng)柱面請(qǐng)求處理memset(cylinders, 0, CYLINDER_NUM * sizeof(int));set_cylinders(cylinders, cylinder_req);int pre_cylinder_head = cylinder_head;int head_move_sum = 0;printf("head's movement: ");// 打印一開始磁頭處于柱面位置if (cylinders[cylinder_head] == 0) {printf("%d ", cylinder_head);}// 找到兩個(gè)方向的最遠(yuǎn)請(qǐng)求int cylinder_req_min = cylinder_req[0];int cylinder_req_max = cylinder_req[0];for(int i = 0; i < CYLINDER_REQ_NUM; ++i) {int cylinder_id = cylinder_req[i];if (cylinder_req_min > cylinder_id) {cylinder_req_min = cylinder_id;}if (cylinder_req_max < cylinder_id) {cylinder_req_max = cylinder_id;}}// 如果磁頭一開始在兩個(gè)最遠(yuǎn)請(qǐng)求外側(cè),那么首先掃到最近一側(cè)的盡頭if (cylinder_head < cylinder_req_min) {cylinder_head = cylinder_req_min;head_move_sum += cylinder_req_min - cylinder_head;} else if (cylinder_head > cylinder_req_max) {cylinder_head = cylinder_req_max;head_move_sum += cylinder_req_max - cylinder_req_min;}// 向一個(gè)方向掃描while (cylinder_head >= cylinder_req_min && cylinder_head <= cylinder_req_max) {// 如果磁頭在請(qǐng)求處理的柱面上while (cylinders[cylinder_head] > 0) {printf("%d ", cylinder_head);// 將磁頭移動(dòng)距離加到磁頭移動(dòng)總距離中head_move_sum += abs_int(cylinder_head - pre_cylinder_head);// 更新磁頭上一次處在的位置pre_cylinder_head = cylinder_head;// 處理后的柱面在硬盤上的請(qǐng)求數(shù)減一cylinders[cylinder_head]--;}// 如果head_dir為0,向朝0的方向掃描if (head_dir == 0) {cylinder_head--;} else {// 如果head_dir為1,向朝CYLINDER_NUM的方向掃描cylinder_head++;}}// 令磁頭到達(dá)一側(cè)最遠(yuǎn)請(qǐng)求if (cylinder_head == cylinder_req_min - 1) {cylinder_head = cylinder_req_min;}if (cylinder_head == cylinder_req_max + 1) {cylinder_head = cylinder_req_max;}// 調(diào)轉(zhuǎn)掃描方向if (head_dir == 0) {head_dir = 1;} else {head_dir = 0;}// 向另一個(gè)方向繼續(xù)掃描while (cylinder_head >= cylinder_req_min && cylinder_head <= cylinder_req_max) {while (cylinders[cylinder_head] > 0) {printf("%d ", cylinder_head);head_move_sum += abs_int(cylinder_head - pre_cylinder_head);pre_cylinder_head = cylinder_head;cylinders[cylinder_head]--;}if (head_dir == 0) {cylinder_head--;} else {cylinder_head++;}}printf("\nThe total movement of head = %d cylinders\n", head_move_sum);printf("--------------------------------------------------------\n"); }// C-LOOK循環(huán)電梯調(diào)度算法 void C_LOOK(int *cylinders, int *cylinder_req, int cylinder_head, int head_dir) {printf("\n--------------------------------------------------------\n");printf("HDD Scheduling Algorithm: C-LOOK\n");print_cylinder_req(cylinder_req);print_head_dir(head_dir);printf("\n");// 初始化硬盤柱面,設(shè)置相應(yīng)柱面請(qǐng)求處理memset(cylinders, 0, CYLINDER_NUM * sizeof(int));set_cylinders(cylinders, cylinder_req);int pre_cylinder_head = cylinder_head;int head_move_sum = 0;printf("head's movement: ");// 打印一開始磁頭處于柱面位置if (cylinders[cylinder_head] == 0) {printf("%d ", cylinder_head);}// 找到兩個(gè)方向的最遠(yuǎn)請(qǐng)求int cylinder_req_min = cylinder_req[0];int cylinder_req_max = cylinder_req[0];for(int i = 0; i < CYLINDER_REQ_NUM; ++i) {int cylinder_id = cylinder_req[i];if (cylinder_req_min > cylinder_id) {cylinder_req_min = cylinder_id;}if (cylinder_req_max < cylinder_id) {cylinder_req_max = cylinder_id;}}// 如果磁頭一開始在兩個(gè)最遠(yuǎn)請(qǐng)求外側(cè),那么首先掃到最近一側(cè)的盡頭if (cylinder_head < cylinder_req_min) {cylinder_head = cylinder_req_min;head_move_sum += cylinder_req_min - cylinder_head;} else if (cylinder_head > cylinder_req_max) {cylinder_head = cylinder_req_max;head_move_sum += cylinder_req_max - cylinder_req_min;}// 向一個(gè)方向掃描while (cylinder_head >= cylinder_req_min && cylinder_head <= cylinder_req_max) {// 如果磁頭在請(qǐng)求處理的柱面上while (cylinders[cylinder_head] > 0) {printf("%d ", cylinder_head);// 將磁頭移動(dòng)距離加到磁頭移動(dòng)總距離中head_move_sum += abs_int(cylinder_head - pre_cylinder_head);// 更新磁頭上一次處在的位置pre_cylinder_head = cylinder_head;// 處理后的柱面在硬盤上的請(qǐng)求數(shù)減一cylinders[cylinder_head]--;}// 如果head_dir為0,向朝0的方向掃描if (head_dir == 0) {cylinder_head--;} else {// 如果head_dir為1,向朝CYLINDER_NUM的方向掃描cylinder_head++;}}// 令磁頭到達(dá)另一側(cè)最遠(yuǎn)請(qǐng)求head_move_sum += cylinder_req_max - cylinder_req_min;if (cylinder_head == cylinder_req_min - 1) {cylinder_head = cylinder_req_max;}if (cylinder_head == cylinder_req_max + 1) {cylinder_head = cylinder_req_min;}pre_cylinder_head = cylinder_head;// 向同一方向繼續(xù)掃描while (cylinder_head >= cylinder_req_min && cylinder_head <= cylinder_req_max) {while (cylinders[cylinder_head] > 0) {printf("%d ", cylinder_head);head_move_sum += abs_int(cylinder_head - pre_cylinder_head);pre_cylinder_head = cylinder_head;cylinders[cylinder_head]--;}if (head_dir == 0) {cylinder_head--;} else {cylinder_head++;}}printf("\nThe total movement of head = %d cylinders\n", head_move_sum);printf("--------------------------------------------------------\n"); }// 找到距離當(dāng)前磁頭最近的請(qǐng)求處理的柱面 int find_cylinder_min_seek_dis(int *cylinders, int cylinder_head) {// 朝0方向查找的變量int find_head_dir0 = cylinder_head;// 朝CYLINDER_NUM方向查找的變量int find_head_dir1 = cylinder_head;while (find_head_dir0 >= 0 || find_head_dir1 < CYLINDER_NUM) {// 每次兩個(gè)變量移動(dòng)相同距離查找,當(dāng)找到有請(qǐng)求的柱面,就是距離磁頭最近的柱面,直接返回if (find_head_dir0 >= 0) {if (cylinders[find_head_dir0] > 0) {return find_head_dir0;}find_head_dir0--;}if (find_head_dir1 < CYLINDER_NUM) {if (cylinders[find_head_dir1] > 0) {return find_head_dir1;}find_head_dir1++;}}// 沒有請(qǐng)求處理的柱面則返回-1return -1; }// 將I/O請(qǐng)求塊的柱面在硬盤上設(shè)置相應(yīng)的請(qǐng)求 void set_cylinders(int *cylinders, int *cylinder_req) {for(int i = 0; i < CYLINDER_REQ_NUM; ++i) {int cylinder_id = cylinder_req[i];// 可能同一柱面不止一個(gè)請(qǐng)求,所以請(qǐng)求加一cylinders[cylinder_id]++;} }// 打印I/O請(qǐng)求塊的柱面的信息 void print_cylinder_req(int *cylinder_req) {printf("cylinder request: ");for(int i = 0; i < CYLINDER_REQ_NUM; ++i) {printf("%d ", cylinder_req[i]);}printf("\n"); }// 打印開始時(shí)磁頭掃描方向 void print_head_dir(int head_dir) {printf("The direction of head movement in the beginning: toward cylinder ");if (head_dir == 0) {printf("0\n");} else {printf("%d\n", CYLINDER_NUM - 1);} }int main () {int cylinders[CYLINDER_NUM];int cylinder_req[CYLINDER_REQ_NUM];int cylinder_head;int head_dir;// 生成隨機(jī)數(shù)的方式產(chǎn)生測(cè)試樣例/*srand((unsigned) time(NULL));int num;for (int i = 0; i < CYLINDER_REQ_NUM; ++i) {num = rand() % CYLINDER_NUM;cylinder_req[i] = num;}num = rand() % CYLINDER_NUM;cylinder_head = num;num = rand() % 2;head_dir = num;*/// 手動(dòng)輸入的方式產(chǎn)生測(cè)試樣例printf("Please input the queue with requests for cylinders:\n");for(int i = 0; i < CYLINDER_REQ_NUM; ++i) {scanf("%d", &cylinder_req[i]);}printf("Please input the head's position of cylinder: ");scanf("%d", &cylinder_head);printf("Please input the direction of head movement(0: toward cylinder 0, 1: toward cylinder %d): ", CYLINDER_NUM - 1);scanf("%d", &head_dir);FCFS(cylinders, cylinder_req, cylinder_head);SSTF(cylinders, cylinder_req, cylinder_head);SCAN(cylinders, cylinder_req, cylinder_head, head_dir);C_SCAN(cylinders, cylinder_req, cylinder_head, head_dir);LOOK(cylinders, cylinder_req, cylinder_head, head_dir);C_LOOK(cylinders, cylinder_req, cylinder_head, head_dir); }執(zhí)行命令:
gcc HDD_scheduling.c ./a.out驗(yàn)證各個(gè)磁盤調(diào)度算法的正確性
在宏定義處設(shè)置I/O請(qǐng)求塊的柱面數(shù)目、總的柱面數(shù)目:
#define CYLINDER_REQ_NUM 8 // I/O請(qǐng)求塊的柱面數(shù)目 #define CYLINDER_NUM 200 // 總的柱面數(shù)目測(cè)試用例1:
首先按照教材上的用例測(cè)試:
#define CYLINDER_REQ_NUM 8 // I/O請(qǐng)求塊的柱面數(shù)目 #define CYLINDER_NUM 200 // 總的柱面數(shù)目98 183 37 122 14 124 65 67 53 098 183 37 122 14 124 65 67 53 1先來先服務(wù)調(diào)度算法:
可以看到,
一開始,磁頭所在的柱面為53;
然后按照I/O請(qǐng)求塊的柱面順序依次處理柱面請(qǐng)求,得到的磁頭移動(dòng)路徑和磁頭移動(dòng)總距離與教材相同。
過程符合先來先服務(wù)調(diào)度算法。
最短尋道時(shí)間優(yōu)先調(diào)度算法:
可以看到,
一開始,磁頭所在的柱面為53;
然后按照距離當(dāng)前磁頭所在柱面最短距離的柱面依次處理柱面請(qǐng)求,得到的磁頭移動(dòng)路徑和磁頭移動(dòng)總距離與教材相同。
過程符合最短尋道時(shí)間優(yōu)先調(diào)度算法。
掃描調(diào)度算法:
首先磁頭向朝0方向掃描:
可以看到,
一開始,磁頭所在的柱面為53;
然后按照掃描方向的經(jīng)過柱面依次處理柱面請(qǐng)求,到達(dá)0后,再向朝柱面199方向依次掃描,得到的磁頭移動(dòng)路徑和磁頭移動(dòng)總距離與教材相同。
過程符合掃描調(diào)度算法。
如果首先磁頭向朝柱面199方向掃描:
可以看到,
一開始,磁頭所在的柱面為53;
然后按照掃描方向的經(jīng)過柱面依次處理柱面請(qǐng)求,到達(dá)柱面199后,再向朝0方向依次掃描。
過程符合掃描調(diào)度算法。
循環(huán)掃描調(diào)度算法:
首先磁頭向朝0方向掃描:
可以看到,
一開始,磁頭所在的柱面為53;
然后按照掃描方向的經(jīng)過柱面依次處理柱面請(qǐng)求,到達(dá)0后,直接到達(dá)柱面199,再向朝0方向依次掃描。
過程符合循環(huán)掃描調(diào)度算法。
如果首先磁頭向朝柱面199方向掃描:
可以看到,
一開始,磁頭所在的柱面為53;
然后按照掃描方向的經(jīng)過柱面依次處理柱面請(qǐng)求,到達(dá)柱面199后,直接到達(dá)柱面0,再向朝柱面199方向依次掃描,得到的磁頭移動(dòng)路徑和磁頭移動(dòng)總距離與教材相同。
過程符合循環(huán)掃描調(diào)度算法。
LOOK電梯調(diào)度算法:
首先磁頭向朝0方向掃描:
可以看到,
一開始,磁頭所在的柱面為53;
然后按照掃描方向的經(jīng)過柱面依次處理柱面請(qǐng)求,到達(dá)朝0方向最遠(yuǎn)的柱面請(qǐng)求柱面14后,再向朝柱面199方向依次掃描,得到的磁頭移動(dòng)路徑和磁頭移動(dòng)總距離與教材相同。
過程符合LOOK電梯調(diào)度算法。
如果首先磁頭向朝柱面199方向掃描:
可以看到,
一開始,磁頭所在的柱面為53;
然后按照掃描方向的經(jīng)過柱面依次處理柱面請(qǐng)求,到達(dá)朝柱面199方向最遠(yuǎn)的柱面請(qǐng)求柱面183后,再向朝0方向依次掃描。
過程符合LOOK電梯調(diào)度算法。
C-LOOK循環(huán)電梯調(diào)度算法:
首先磁頭向朝0方向掃描:
可以看到,
一開始,磁頭所在的柱面為53;
然后按照掃描方向的經(jīng)過柱面依次處理柱面請(qǐng)求,到達(dá)朝0方向最遠(yuǎn)的請(qǐng)求柱面14后,直接到達(dá)朝柱面199方向最遠(yuǎn)的請(qǐng)求柱面183,再向朝0方向依次掃描。
過程符合C-LOOK循環(huán)電梯調(diào)度算法。
如果首先磁頭向朝柱面199方向掃描:
可以看到,
一開始,磁頭所在的柱面為53;
然后按照掃描方向的經(jīng)過柱面依次處理柱面請(qǐng)求,到達(dá)朝柱面199方向最遠(yuǎn)的請(qǐng)求柱面183后,直接到達(dá)朝0方向最遠(yuǎn)的請(qǐng)求柱面14,再向柱面199方向依次掃描,得到的磁頭移動(dòng)路徑和磁頭移動(dòng)總距離與教材相同。
過程符合C-LOOK循環(huán)電梯調(diào)度算法。
測(cè)試用例2:
#define CYLINDER_REQ_NUM 8 // I/O請(qǐng)求塊的柱面數(shù)目 #define CYLINDER_NUM 200 // 總的柱面數(shù)目176 17 23 42 5 21 186 92 156 0執(zhí)行截圖:
可以看到,磁頭的移動(dòng)路徑和移動(dòng)總距離都正確。
測(cè)試用例3:
#define CYLINDER_REQ_NUM 8 // I/O請(qǐng)求塊的柱面數(shù)目 #define CYLINDER_NUM 200 // 總的柱面數(shù)目81 87 138 193 99 99 79 67 14 1這個(gè)樣例中,磁頭一開始的位置比朝0方向的最遠(yuǎn)請(qǐng)求柱面距離0更近,中間有兩個(gè)柱面請(qǐng)求為同一個(gè)柱面。
執(zhí)行截圖:
可以看到,磁頭的移動(dòng)路徑和移動(dòng)總距離都正確。
LOOK算法和C-LOOK算法的移動(dòng)路徑和移動(dòng)總距離都相同,因?yàn)榇蓬^第一次朝一個(gè)方向掃時(shí)就已經(jīng)處理完所有的柱面請(qǐng)求,符合算法。
測(cè)試用例4:
#define CYLINDER_REQ_NUM 8 // I/O請(qǐng)求塊的柱面數(shù)目 #define CYLINDER_NUM 200 // 總的柱面數(shù)目53 53 43 53 43 53 53 53 53 1這個(gè)樣例中,磁頭一開始的位置和第一個(gè)請(qǐng)求的柱面位置一樣,中間有多個(gè)重復(fù)請(qǐng)求的柱面位置。
執(zhí)行截圖:
可以看到,磁頭的移動(dòng)路徑和移動(dòng)總距離都正確。
C-LOOK算法中,磁頭首先到達(dá)最遠(yuǎn)請(qǐng)求柱面53,然后直接到達(dá)另一側(cè)的最遠(yuǎn)請(qǐng)求柱面43,所有磁頭移動(dòng)總距離為0,符合算法。
總結(jié)
以上是生活随笔為你收集整理的操作系统实验报告18:硬盘柱面访问调度算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 操作系统实验报告17:请求页面置换算法
- 下一篇: java信息管理系统总结_java实现科