第一篇:操作系統(tǒng)課設(shè)任務(wù)
一、操作系統(tǒng)課程設(shè)計(jì)要求:
1.每個(gè)學(xué)生從以下給定題目中選做至少一項(xiàng),也可以針對(duì)操作系統(tǒng)課程實(shí)驗(yàn)已完成的題目進(jìn)行擴(kuò)充完善; 2.設(shè)計(jì)周周末向各班學(xué)習(xí)委員交源程序、設(shè)計(jì)報(bào)告的電子版和打印版; 3.編程工具不限
二、操作系統(tǒng)課程設(shè)計(jì)題目:(在以下題目中任選一個(gè)題目進(jìn)行設(shè)計(jì))
1.進(jìn)程同步問題(信號(hào)量機(jī)制)(任選其一)1)生產(chǎn)者消費(fèi)者問題 2)哲學(xué)家進(jìn)餐問題 3)讀者-寫者問題 4)吃水果問題 5)售票員售票問題
2.進(jìn)程(作業(yè))調(diào)度算法(任選其中三種算法)1)先來先服務(wù)算法 2)短進(jìn)程(作業(yè))優(yōu)先算法 3)優(yōu)先數(shù)優(yōu)先算法 4)最高響應(yīng)比優(yōu)先算法 5)時(shí)間片輪轉(zhuǎn)調(diào)度算法
3.實(shí)時(shí)調(diào)度算法 1)最早截止時(shí)間優(yōu)先 2)最低松弛度優(yōu)選 4.銀行家算法(死鎖避免)
5.動(dòng)態(tài)分區(qū)分配算法(連續(xù)存儲(chǔ)器管理方式)
首次適應(yīng)算法、循環(huán)首次適應(yīng)算法、最佳適應(yīng)算法、最差適應(yīng)算法 6.頁面置換算法
最佳置換算法OPT、先進(jìn)先出算法FIFO、最近最久未使用算法LRU 7.磁盤調(diào)度算法
先來先服務(wù)算法、最短尋道時(shí)間優(yōu)先算法、掃描算法(電梯調(diào)度算法)8.緩沖池管理
三、操作系統(tǒng)課程設(shè)計(jì)任務(wù)書
封皮
指導(dǎo)教師評(píng)語
第一部分:需求分析(課題描述、課題目的、理論依據(jù))第二部分:概要設(shè)計(jì)(設(shè)計(jì)方法、技術(shù)、運(yùn)行環(huán)境等)第三部分:詳細(xì)設(shè)計(jì)(流程圖、程序主要代碼)
第四部分:運(yùn)行結(jié)果及分析(運(yùn)行結(jié)果(可以截圖)、結(jié)果詳細(xì)分析)第五部分:總結(jié)和心得 參考文獻(xiàn): 附錄:程序源代碼
注:程序詳細(xì)代碼附在電子版中即可,打印版可不打印。
課程設(shè)計(jì)時(shí)間:2018年1月1日——2018年1月5日
第二篇:操作系統(tǒng)課設(shè)
操作系統(tǒng)課程設(shè)計(jì)
一實(shí)驗(yàn)?zāi)康?/p>
在多道程序或多任務(wù)系統(tǒng)中,系統(tǒng)中同時(shí)處于就緒態(tài)的進(jìn)程有若干個(gè),也就是說能運(yùn)行的進(jìn)程數(shù)遠(yuǎn)遠(yuǎn)大于處理機(jī)個(gè)數(shù)。為了使系統(tǒng)中的各進(jìn)程能有條不紊地進(jìn)行,必須選擇某種調(diào)度策略,以選擇一進(jìn)程占用處理機(jī)。要求學(xué)生設(shè)計(jì)一個(gè)模擬單處理機(jī)調(diào)度的算法,以加深對(duì)處理機(jī)調(diào)度的概念理解。
通過自己變成來實(shí)現(xiàn)頁面調(diào)度算法,進(jìn)一步理解頁面調(diào)度算法 的概念及含義,提高對(duì)頁面調(diào)度算法的認(rèn)識(shí),同時(shí)提高自己的動(dòng)手實(shí)踐能力。加深我們對(duì)主存與輔助存儲(chǔ)器統(tǒng)一管理、邏輯地址與物理地址轉(zhuǎn)換、部分裝入和部分替換問題的理解,同時(shí),有利于我們對(duì)虛擬存儲(chǔ)技術(shù)的理解。
為了了解系統(tǒng)的資源分配情況,假定系統(tǒng)的任何一種資源在 任一時(shí)刻只能被一個(gè)進(jìn)程使用。任何進(jìn)程已經(jīng)占用的資源只能由進(jìn)程自己釋放,而不能由其他進(jìn)程搶占。當(dāng)進(jìn)程申請(qǐng)的資源不能滿足時(shí),必須等待。因此,只要資源分配算法能保證進(jìn)程的資源請(qǐng)求,且不出現(xiàn)循環(huán)等待,則系統(tǒng)不會(huì)出現(xiàn)死鎖。
編寫模擬系統(tǒng)進(jìn)行資源調(diào)度的程序,一個(gè)是隨機(jī)算法,即只 要系統(tǒng)剩余資源能滿足進(jìn)程的當(dāng)前請(qǐng)求,就立即將資源分配給進(jìn)程,以觀察死鎖產(chǎn)生情況;一個(gè)是采用銀行家算法,有效地避免死鎖的產(chǎn)生。
模擬進(jìn)程的資源分配算法,了解死鎖的產(chǎn)生和避免的辦法。通過設(shè)計(jì)一個(gè)磁盤調(diào)度模擬系統(tǒng),深入理解磁盤的工作原理,從而使磁盤調(diào)度更加形象化,容易使人理解,使磁盤調(diào)度的特點(diǎn)更簡(jiǎn)單明了,能使使用者加深對(duì)磁盤調(diào)度算法的理解。具體實(shí)現(xiàn)為,運(yùn)用一門高級(jí)編程語言編寫程序模擬磁盤調(diào)度的過程,采用先來先服務(wù)算法和電梯算法,模擬并輸出存取臂的移動(dòng)順序,并計(jì)算存取臂移動(dòng)的磁道總數(shù)。能夠處理以下的情形:
(1)可根據(jù)需要輸入當(dāng)前磁頭的位置,磁頭移動(dòng)方向;(2)能夠輸入柱面數(shù),磁道訪問序列等參數(shù),并能夠顯示調(diào)度結(jié)果(磁盤訪問請(qǐng)求的磁道號(hào)以及磁頭移動(dòng)的總磁道數(shù))。
二、實(shí)驗(yàn)內(nèi)容
利用C++實(shí)驗(yàn)以下算法: 處理機(jī)管理中:
(1)先來先服務(wù)算法(FCFS)
實(shí)驗(yàn)題目:
<1>假設(shè)系統(tǒng)中有3~5個(gè)進(jìn)程,每個(gè)進(jìn)程由一個(gè)進(jìn)程控制塊(PCB)來標(biāo)識(shí)。
<2>設(shè)置一個(gè)隊(duì)首指針head,用來指出最先進(jìn)入系統(tǒng)的進(jìn)程,各就緒進(jìn)程通過鏈接指針連在一起。
<3>處理機(jī)調(diào)度時(shí)總是選擇隊(duì)首指針指向的進(jìn)程投入運(yùn)行。由于本實(shí)驗(yàn)是模擬實(shí)驗(yàn),所以對(duì)被選中進(jìn)程并不實(shí)際啟動(dòng)運(yùn)行,而只是執(zhí)行。估計(jì)運(yùn)行時(shí)間減1,用這個(gè)操作來模擬進(jìn)程的一次運(yùn)行,而且省去進(jìn)程的現(xiàn)場(chǎng)保護(hù)和現(xiàn)場(chǎng)恢復(fù)工作。
<4>在所設(shè)計(jì)的程序中應(yīng)有顯示或打印語句,能顯示或打印正運(yùn)行的進(jìn)程名字、已運(yùn)行時(shí)間、還剩時(shí)間、就緒對(duì)列中進(jìn)程名字等。所有進(jìn)程運(yùn)行完成時(shí),給出各進(jìn)程的周轉(zhuǎn)時(shí)間和平均周轉(zhuǎn)時(shí)間.數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)如下:
struct PCB
//定義進(jìn)程控制塊
{
char ID[3];
//進(jìn)程號(hào)
char name[10];
//進(jìn)程名
char state;
//運(yùn)行狀態(tài)
int arrivetime;//到達(dá)時(shí)間
int starttime;//進(jìn)程開始時(shí)間
int finishtime;//進(jìn)程結(jié)束時(shí)間
int servicetime;
//運(yùn)行時(shí)間
float turnaroundtime;//周轉(zhuǎn)時(shí)間
float weightedturnaroundtime;//帶權(quán)周轉(zhuǎn)時(shí)間
struct PCB *next;//指向下個(gè)進(jìn)程
};
(2)時(shí)間片輪算法
實(shí)驗(yàn)題目:
<1>假設(shè)系統(tǒng)中有3~5個(gè)進(jìn)程,每個(gè)進(jìn)程由一個(gè)進(jìn)程控制塊(PCB)來代表。
<2>按照進(jìn)程到達(dá)的先后順序排成一個(gè)循環(huán)隊(duì)列,設(shè)一個(gè)隊(duì)首指針指向第一個(gè)到達(dá)的進(jìn)程的首址。另外再設(shè)一個(gè)當(dāng)前運(yùn)行進(jìn)程指針,指向當(dāng)前正運(yùn)行的進(jìn)程。
<3>執(zhí)行處理機(jī)調(diào)度時(shí),首先選擇隊(duì)首的第一個(gè)進(jìn)程運(yùn)行。<4>由于本實(shí)驗(yàn)是模擬實(shí)驗(yàn),所以對(duì)被選中進(jìn)程并不實(shí)際啟動(dòng)運(yùn)行,而只是執(zhí)行:
估計(jì)運(yùn)行時(shí)間減1 用這個(gè)操作來模擬進(jìn)程的一次運(yùn)行。
<5>進(jìn)程運(yùn)行一次后,以后的調(diào)度則將當(dāng)前指針依次下移一個(gè)位置,指向下一個(gè)進(jìn)程,即調(diào)整當(dāng)前運(yùn)行指針指向該進(jìn)程的鏈接指針?biāo)高M(jìn)程,以指示應(yīng)運(yùn)行進(jìn)程,同時(shí)
還應(yīng)判斷該進(jìn)程的剩余運(yùn)行時(shí)間是否為0.若不為0,則等待下一輪的運(yùn)行,若該進(jìn)程的剩余運(yùn)行時(shí)間為0,則將該進(jìn)程的狀態(tài)置為完成狀態(tài)“C”,并退出循環(huán)隊(duì)列。<6>若就緒隊(duì)列不空,則重復(fù)上述的步驟(4)和(5)直到所有進(jìn)程都運(yùn)行完為止。
<7>在所設(shè)計(jì)的調(diào)度程序中,應(yīng)包含顯示或打印語句吧,已便顯示或打印每次選中進(jìn)程的名稱及運(yùn)行一次后隊(duì)列的變化情況。數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)如下:
typedef struct pcb
//進(jìn)程控制塊定義
{
char pname[N];
//進(jìn)程名
int runtime;
//運(yùn)行時(shí)間
int arrivetime;
char state;
struct pcb*next;
}PCB;PCB head_input;
PCB head_run;
PCB *pcb_input;
void inputprocess();
函數(shù)
int readydata();
int runprocess();
進(jìn)程的函數(shù)
int readyprocess();
static char R='r',C='c';
量
unsigned long current;
//到達(dá)時(shí)間
//進(jìn)程狀態(tài) //鏈接指針
//就緒隊(duì)列頭指針 //運(yùn)行隊(duì)列頭指針
//判斷是否有就緒進(jìn)程的 //運(yùn)行進(jìn)程的函數(shù)
//檢查就緒隊(duì)列并準(zhǔn)備運(yùn)行
//聲明一個(gè)文件指針
//記錄系統(tǒng)當(dāng)前時(shí)間的變
//建立進(jìn)程的函數(shù)
(3)優(yōu)先級(jí)調(diào)度算法
實(shí)驗(yàn)題目:
<1>假設(shè)系統(tǒng)中有3~5個(gè)進(jìn)程,每個(gè)進(jìn)程由一個(gè)進(jìn)程控制塊(PCB)來代表。進(jìn)程的優(yōu)先數(shù)、要求運(yùn)行時(shí)間和估計(jì)運(yùn)行
時(shí)間由用戶程序任意設(shè)計(jì),且優(yōu)先數(shù)越低,優(yōu)先級(jí)越高。調(diào)度時(shí),總是選擇優(yōu)先級(jí)最高的進(jìn)程運(yùn)行。
<2>為了調(diào)度方便,設(shè)計(jì)一個(gè)指針指向就緒隊(duì)列的第一個(gè)進(jìn)程。另外再設(shè)一個(gè)當(dāng)前運(yùn)行進(jìn)程指針,指向當(dāng)前正運(yùn)行的進(jìn)程。
<3>處理機(jī)調(diào)度時(shí),總是選擇已經(jīng)到達(dá)隊(duì)列的優(yōu)先級(jí)最高的進(jìn)程運(yùn)行。為了采用 動(dòng)態(tài)優(yōu)先級(jí)調(diào)度,進(jìn)程每運(yùn)行一次,其優(yōu)先級(jí)就減1。由于本實(shí)驗(yàn)是模擬實(shí)驗(yàn),所以對(duì)被選中進(jìn)程并不實(shí)際啟動(dòng)運(yùn)行,而只是執(zhí)行:
優(yōu)先數(shù)加1和估計(jì)運(yùn)行時(shí)間減1 用這個(gè)操作來模擬進(jìn)程的一次運(yùn)行。
<4>進(jìn)程運(yùn)行一次后,若剩余的運(yùn)行時(shí)間不為0,且其優(yōu)先級(jí)低于就緒隊(duì)列的其他進(jìn)程的優(yōu)先級(jí),則選擇一個(gè)高優(yōu)先級(jí)進(jìn)程搶占CPU;若剩余運(yùn)行時(shí)間為0,則把它的狀態(tài)改為完成狀態(tài)“C”,并撤出就緒隊(duì)列。
<5>若就緒隊(duì)列不空,則重復(fù)上述的步驟(3)和(4)直到所有進(jìn)程都運(yùn)行完為止。
<6>在所設(shè)計(jì)的程序中應(yīng)有顯示或打印語句,以顯示或打印每次被選中進(jìn)程的進(jìn)程名字、運(yùn)行一次后進(jìn)程的變化以及就緒隊(duì)列中的各進(jìn)程排隊(duì)情況等。數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)如下:
struct pcb {
/* 定義進(jìn)程控制塊PCB */
char name[10];
//進(jìn)程名
char state;
//進(jìn)程狀態(tài)
int super;
//優(yōu)先級(jí)數(shù)
int ntime;
//需要運(yùn)行時(shí)間
int rtime;
//已運(yùn)行時(shí)間 頁面替換算法中:
(1)先進(jìn)先出頁面替換算法(FIFO)(2)最近最少使用頁面替換算法(LRU)(3)最少使用頻率頁面替換算法(LFU)
數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)如下:
struct PageFrame
//頁框結(jié)構(gòu) {
int id;
//頁框號(hào)
int pageId;
//駐留的頁號(hào)
int visitedCount;//駐留頁計(jì)數(shù)器,訪問加1 int unvisitedCount;//最近訪問,訪問清零,未訪問加1 bool replace;//將被淘汰為true int stayTime;
//駐留時(shí)間計(jì)數(shù) int nextsite;};銀行家算法 實(shí)驗(yàn)題目
<1>
為了觀察死鎖產(chǎn)生和避免的情況,要求設(shè)計(jì)3~4個(gè)并發(fā)進(jìn)程,共享系統(tǒng)的10個(gè)同類補(bǔ)課搶占的資源。各進(jìn)程是動(dòng)態(tài)進(jìn)行資源的申請(qǐng)和釋放。
<2>
用隨機(jī)算法和銀行家算法分別設(shè)計(jì)一個(gè)資源分配程序,運(yùn)行這兩個(gè)程序,觀察系統(tǒng)運(yùn)行情況,并對(duì)系統(tǒng)運(yùn)行的每一步情況進(jìn)行顯示。
程序中使用的數(shù)據(jù)結(jié)構(gòu)及主要符號(hào)說明
初始化這組進(jìn)程的最大資源請(qǐng)求和依次申請(qǐng)的資源序列,把進(jìn)程已占用和需求的資源情況記錄在進(jìn)程控制塊中,假定進(jìn)程控制塊的格式如下圖所示;
進(jìn)程狀態(tài)有:就緒、等待和完成。當(dāng)系統(tǒng)不能滿足進(jìn)程的資源請(qǐng)求時(shí),進(jìn)程處于等待態(tài)。
“資源需求總量”表示進(jìn)程運(yùn)行過程中對(duì)資源的最大需求量。顯然每個(gè)進(jìn)程的資源需求總量不應(yīng)超過系統(tǒng)擁有的資源總量。“已占資源量”表示進(jìn)程目前已經(jīng)得到但還未歸還的資源量。因此,進(jìn)程在以后還需要的剩余資源量等于資源需要總量減去已占資源量?!爱?dāng)前申請(qǐng)量”指進(jìn)程都拿過去按運(yùn)行時(shí)需要申請(qǐng)的資源量。銀行家算法分配資源的原則是:
(1)當(dāng)某個(gè)進(jìn)程提出資源請(qǐng)求時(shí),假定先分配給它,之后調(diào)用系統(tǒng)安全性檢查算法,進(jìn)行系統(tǒng)安全性檢查,若系統(tǒng)安全,須分配變?yōu)檎娣峙?。否則作廢假分配,讓進(jìn)程等待。(2)系統(tǒng)安全性檢查算法。驅(qū)動(dòng)調(diào)度算法中:
作為操作系統(tǒng)的輔助存儲(chǔ)器,用來存放文件的磁盤是一類高速大容量旋轉(zhuǎn)型存儲(chǔ)設(shè)備,在繁重的I/O負(fù)載下,同時(shí)會(huì)有若干傳輸請(qǐng)求來到并等待處理,系統(tǒng)必須采用一種調(diào)度策略,按照最佳次序執(zhí)行要求訪問的諸多請(qǐng)求,減少為若干I/O請(qǐng)求服務(wù)所需消耗的總時(shí)間。
磁盤驅(qū)動(dòng)調(diào)度對(duì)磁盤的效率有重要影響。磁盤驅(qū)動(dòng)調(diào)度算法的好壞直接影響輔助存儲(chǔ)器的效率,從而影響計(jì)算機(jī)系統(tǒng)的整體效率。(1)電梯調(diào)度算法(2)最短查找時(shí)間優(yōu)先算法(3)先來先服務(wù)算法
三、實(shí)驗(yàn)心得
通過本次課程設(shè)計(jì),我認(rèn)識(shí)到要將操作系統(tǒng)這門計(jì)算機(jī)專業(yè)課學(xué)好不易——不僅僅是要把書上的基本知識(shí)學(xué)好,而且還要不斷進(jìn)行實(shí)踐,將所學(xué)與實(shí)踐操作結(jié)合起來才能更好地鞏固所學(xué),才能提高自己實(shí)踐能力。在以后的學(xué)習(xí)中一方面我要不斷的鞏固自己所學(xué)的理論知識(shí),一方面還要多參加實(shí)際操作工作以便提高自己的實(shí)際操作能力。
第三篇:操作系統(tǒng)課設(shè)
課 程 設(shè) 計(jì) 報(bào) 告
課程名稱: 計(jì)算機(jī)操作系統(tǒng)
專業(yè)班級(jí):
學(xué) 號(hào): 姓 名: 指導(dǎo)教師: 報(bào)告日期:
計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
目 錄 2 3 實(shí)驗(yàn)?zāi)康?.............................................................................................2 實(shí)驗(yàn)環(huán)境..............................................................................................2 實(shí)驗(yàn)內(nèi)容..............................................................................................2 3.1 3.2 3.3 3.4 3.5 4 實(shí)驗(yàn)一...............................................................................................2 實(shí)驗(yàn)二...............................................................................................2 實(shí)驗(yàn)三...............................................................................................2 實(shí)驗(yàn)四(選做)................................................................................3 實(shí)驗(yàn)五(選做)................................................................................3
設(shè)計(jì)與實(shí)現(xiàn)...........................................................................................3 4.1 4.2 4.3 4.4 實(shí)驗(yàn)一...............................................................................................3 實(shí)驗(yàn)二.............................................................................................10 實(shí)驗(yàn)三.............................................................................................14 實(shí)驗(yàn)四.............................................................................................20 心得體會(huì)............................................................................................43
I
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告 ·掌握Linux操作系統(tǒng)的使用方法; ·了解Linux系統(tǒng)內(nèi)核代碼結(jié)構(gòu); ·掌握實(shí)例操作系統(tǒng)的實(shí)現(xiàn)方法;
實(shí)驗(yàn)?zāi)康?實(shí)驗(yàn)環(huán)境
本次課程設(shè)計(jì)采用的操作系統(tǒng)環(huán)境是windows8、Ubuntu雙系統(tǒng),Ubuntu系統(tǒng)版本號(hào)為14.04,內(nèi)核版本號(hào)為linux 3.13.0;采用的編程環(huán)境為CodeBlocks IDE和QtCreator。3.1 實(shí)驗(yàn)一
實(shí)驗(yàn)內(nèi)容
掌握Linux操作系統(tǒng)的使用方法,包括鍵盤命令、系統(tǒng)調(diào)用;掌握在Linux下的編程環(huán)境。
(1)編寫一個(gè)C程序,其內(nèi)容為實(shí)現(xiàn)文件拷貝的功能。
(2)編寫一個(gè)C程序,其內(nèi)容為分窗口同時(shí)顯示三個(gè)并發(fā)進(jìn)程的運(yùn)行結(jié)果。要求用到Linux下的圖形庫(kù)(GTK/Qt)。
3.2 實(shí)驗(yàn)二
掌握系統(tǒng)調(diào)用的實(shí)現(xiàn)過程,通過編譯內(nèi)核方法,增加一個(gè)新的系統(tǒng)調(diào)用,另編寫一個(gè)應(yīng)用程序,調(diào)用新增加的系統(tǒng)調(diào)用。實(shí)現(xiàn)的功能是:文件拷貝。
3.3 實(shí)驗(yàn)三
掌握增加設(shè)備驅(qū)動(dòng)程序的方法。通過模塊方法,增加一個(gè)新的設(shè)備驅(qū)動(dòng)程序,其功能可以簡(jiǎn)單。(實(shí)現(xiàn)字符設(shè)備的驅(qū)動(dòng))
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
3.4 實(shí)驗(yàn)四(選做)
了解和掌握/proc文件系統(tǒng)的特點(diǎn)和使用方法(1)了解/proc文件的特點(diǎn)和使用方法;
(2)監(jiān)控系統(tǒng)狀態(tài),顯示系統(tǒng)中若干部件使用狀態(tài);(3)用圖形界面實(shí)現(xiàn)系統(tǒng)監(jiān)控狀態(tài);
3.5 實(shí)驗(yàn)五(選做)
設(shè)計(jì)并實(shí)現(xiàn)一個(gè)模擬的文件系統(tǒng)。
多用戶的多級(jí)目錄的文件系統(tǒng)設(shè)計(jì)。多用戶、多級(jí)目錄、login(用戶登錄)、系統(tǒng)初始化(建文件卷,提供登錄模塊)、文件的創(chuàng)建、文件的打開、文件的讀寫、文件關(guān)閉、刪除文件、創(chuàng)建目錄(建立子目錄)、改變當(dāng)前目錄、列出文件目錄、退出。4.1 實(shí)驗(yàn)一
4.1.1 實(shí)驗(yàn)要求
設(shè)計(jì)與實(shí)現(xiàn)
掌握Linux操作系統(tǒng)的使用方法,包括鍵盤命令、系統(tǒng)調(diào)用;掌握在Linux下的編程環(huán)境。4.1.2 具體實(shí)現(xiàn)
本實(shí)驗(yàn)內(nèi)容是用CodeBlocks IDE實(shí)現(xiàn)的,該軟件整合了函數(shù)庫(kù)和編譯器,因此使用起來非常方便。
(1)編寫一個(gè)C程序,其內(nèi)容為實(shí)現(xiàn)文件拷貝的功能。
在windows操作系統(tǒng)上實(shí)現(xiàn)的文件拷貝功能一般使用fopen、fread、fwrite三個(gè)來自標(biāo)準(zhǔn)C函數(shù)庫(kù)的函數(shù)執(zhí)行對(duì)文件的打開、讀、寫操作,而本次實(shí)驗(yàn)要求使用Linux系統(tǒng)的系統(tǒng)調(diào)用open、read、write實(shí)現(xiàn)上述三個(gè)操作。
用到的主要頭文件如下:
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
stdio.h——標(biāo)準(zhǔn)輸入輸出頭文件 string.h——字符串處理相關(guān)頭文件
unistd.h——Linux系統(tǒng)調(diào)用頭文件,比如read、write fcntl.h——包含open系統(tǒng)調(diào)用
errno.h——包含一些調(diào)試錯(cuò)誤時(shí)用到的變量 具體實(shí)現(xiàn)思路:
打開兩個(gè)文件(分別是源文件和目標(biāo)文件,可以是任意字符流形式存儲(chǔ)的文件,包括文本文件、照片等),調(diào)用read函數(shù)讀取源文件的內(nèi)容,將read的返回值作為while循環(huán)的判斷條件,當(dāng)返回值大于0(即還未讀取完畢源文件中的內(nèi)容)時(shí),調(diào)用write執(zhí)行向目標(biāo)文件寫的操作,否則跳出循環(huán),表示源文件已經(jīng)被拷貝到目標(biāo)文件,然后調(diào)用close關(guān)閉源文件和目標(biāo)文件。
代碼編寫完成后,在CodeBlocks上編譯運(yùn)行即可。程序運(yùn)行之前,桌面上只有“教程.docx”,運(yùn)行之后,桌面上新建了“教程副本.docx”,并且“教程.docx”中的內(nèi)容被復(fù)制到了“教程副本.docx”,程序運(yùn)行結(jié)果如下所示:
詳細(xì)代碼見4.1.3。
(2)編寫一個(gè)C程序,其內(nèi)容為分窗口同時(shí)顯示三個(gè)并發(fā)進(jìn)程的運(yùn)行結(jié)果。要求用到Linux下的圖形庫(kù)(GTK/Qt)。
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
本次實(shí)驗(yàn)使用的圖形庫(kù)是跨平臺(tái)的開發(fā)工具Qt。首先下載Qt的安裝包并安裝。Qt安裝完之后,先新建一個(gè)Qt控制臺(tái)應(yīng)用MAIN作為主進(jìn)程,用于調(diào)用三個(gè)并發(fā)的子進(jìn)程。在主進(jìn)程的main函數(shù)中,使用fork創(chuàng)建三個(gè)子進(jìn)程,若進(jìn)程創(chuàng)建成功(即fork函數(shù)返回值等于0),則使用execv函數(shù)進(jìn)入對(duì)應(yīng)的子進(jìn)程(get、copy、put)。主進(jìn)程程序編寫完成后,再新建三個(gè)Qt Widgets Application,分別作為三個(gè)子進(jìn)程get、copy、put(所實(shí)現(xiàn)的功能并不是拷貝)。由于三個(gè)子進(jìn)程窗口顯示的內(nèi)容形式一模一樣,所以以子進(jìn)程get為例。get進(jìn)程的窗口顯示了一下四個(gè)內(nèi)容:當(dāng)前時(shí)間、子進(jìn)程名稱、子進(jìn)程的pid和父進(jìn)程MAIN的pid。用Qt的對(duì)象QDateTime獲取系統(tǒng)當(dāng)前時(shí)間,然后將時(shí)間轉(zhuǎn)換成一個(gè)字符串寫在一個(gè)QLabel類的實(shí)例中,然后將該實(shí)例添加至窗口;直接把當(dāng)前進(jìn)程名稱寫在一個(gè)標(biāo)簽上然后添加至窗口;使用getpid和getppid函數(shù)分別獲取當(dāng)前進(jìn)程號(hào)和父進(jìn)程號(hào),然后調(diào)用sprintf把進(jìn)程號(hào)轉(zhuǎn)換成字符串類型之后寫在標(biāo)簽上并添加至窗口即可。
主進(jìn)程和三個(gè)子進(jìn)程的程序全部編寫完后,直接在Qt上編譯運(yùn)行。程序運(yùn)行結(jié)果如下所示:
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
詳細(xì)代碼見4.1.3。
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
4.1.3 源代碼(1)文件拷貝源代碼
#include
#define SIZE 10
///每次讀取的字符數(shù)目
char * srcFile=“/home/ilbear/桌面/教程.docx”;char *goalFile=“/home/ilbear/桌面/教程副本.docx”;
int main(int argc, const char *argv[]){
int src, goal;
int read_len;
char buff[SIZE];
src=open(srcFile,O_RDONLY);
if(src<0)
{
printf(“Fail to open %sn.”,srcFile);
exit(1);
}
goal=open(goalFile,O_WRONLY|O_CREAT,0666);
if(goal<0)
{
printf(“Fail to open %sn.”,goalFile);
exit(1);
}
while((read_len=read(src,buff,SIZE))>0)
{
write(goal,buff,read_len);
}
close(src);
close(goal);
return 0;}(2)三個(gè)并發(fā)進(jìn)程
#主進(jìn)程MAIN #include
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
{
QCoreApplication a(argc, argv);
pid_t p1,p2,p3;
if((p1=fork())==0)
{
execv(“/home/ilbear/桌面/build-get-Desktop_Qt_5_4_1_GCC_64bit-Debug/get”,NULL);
}
else
{
if((p2=fork())==0)
{
execv(“/home/ilbear/桌面/build-copy-Desktop_Qt_5_4_1_GCC_64bit-Debug/copy”,NULL);
}
else
{
if((p3=fork())==0)
{
execv(“/home/ilbear/桌面/build-put-Desktop_Qt_5_4_1_GCC_64bit-Debug/put”,NULL);
}
}
}
waitpid(p1,NULL,0);
waitpid(p2,NULL,0);
waitpid(p3,NULL,0);
return a.exec();}
#子進(jìn)程get mainwindow.cpp #include “mainwindow.h” #include “ui_mainwindow.h” #include
QMainWindow(parent),ui(new Ui::MainWindow),sharememory1(“share1”){
ui->setupUi(this);
setWindowTitle(“get”);
setWindowFlags(Qt::Dialog);
move(0,0);
resize(500,500);
char str[128],f_id[128];
sprintf(str,“%d”,getpid());
sprintf(f_id,“%d”,getppid());
ui->textBrowser->setText(“get”);
ui->textBrowser_2->setText(str);
ui->textBrowser_3->setText(f_id);
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timerUpDate()));
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
timer->start(1);} MainWindow::~MainWindow(){
delete ui;} void MainWindow::timerUpDate(){
QDateTime time = QDateTime::currentDateTime();
QString str = time.toString(“yyyy-MM-dd hh:mm:ss dddd”);
ui->labelCurDate->setText(str);}
#子進(jìn)程copy mainwindow.cpp #include “mainwindow.h” #include “ui_mainwindow.h” #include
QMainWindow(parent),ui(new Ui::MainWindow),sharememory1(“share1”),sharememory2(“share2”){
char str[128],f_id[128];
ui->setupUi(this);
setWindowTitle(“copy”);
setWindowFlags(Qt::Dialog);
move(500,500);
resize(500,500);
sprintf(str,“%d”,getpid());
sprintf(f_id,“%d”,getppid());
ui->textBrowser->setText(“copy”);
ui->textBrowser_2->setText(str);
ui->textBrowser_3->setText(f_id);
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timerUpDate()));
timer->start(1);} MainWindow::~MainWindow(){
delete ui;} void MainWindow::timerUpDate(){
QDateTime time = QDateTime::currentDateTime();
QString str = time.toString(“yyyy-MM-dd hh:mm:ss dddd”);
ui->labelCurDate->setText(str);}
#子進(jìn)程put mainwindow.cpp #include “mainwindow.h” #include “ui_mainwindow.h”
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
#include
QMainWindow(parent),ui(new Ui::MainWindow),sharememory2(“share2”){
char str[128],f_id[128];
ui->setupUi(this);
setWindowTitle(“put”);
setWindowFlags(Qt::Dialog);
move(1000,0);
resize(500,500);
sprintf(str,“%d”,getpid());
sprintf(f_id,“%d”,getppid());
ui->textBrowser->setText(“put”);
ui->textBrowser_2->setText(str);
ui->textBrowser_3->setText(f_id);
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timerUpDate()));
timer->start(1);} MainWindow::~MainWindow(){
delete ui;} void MainWindow::timerUpDate(){
QDateTime time = QDateTime::currentDateTime();
QString str = time.toString(“yyyy-MM-dd hh:mm:ss dddd”);
ui->labelCurDate->setText(str);} 4.2 實(shí)驗(yàn)二
4.2.1 實(shí)驗(yàn)要求
掌握系統(tǒng)調(diào)用的實(shí)現(xiàn)過程,通過編譯內(nèi)核方法,增加一個(gè)新的系統(tǒng)調(diào)用,另編寫一個(gè)應(yīng)用程序,調(diào)用新增加的系統(tǒng)調(diào)用。4.2.2 具體實(shí)現(xiàn)(1)系統(tǒng)調(diào)用的原理
用戶進(jìn)程不能訪問內(nèi)核所占內(nèi)存空間,也不能調(diào)用內(nèi)核函數(shù)。進(jìn)程調(diào)用一個(gè)特殊的指令,這個(gè)指令會(huì)跳到一個(gè)事先定義的內(nèi)核中的一個(gè)位置。在Intel CPU中,由中斷INT 0x80實(shí)現(xiàn)。(與DOS功能調(diào)用int0x21很相似)跳轉(zhuǎn)到的內(nèi)核位置叫做sysem_call。檢查系統(tǒng)調(diào)用號(hào),這個(gè)號(hào)碼代表進(jìn)程請(qǐng)求哪種服務(wù)。然后,它查看系統(tǒng)
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
調(diào)用表(sys_call_table)找到所調(diào)用的內(nèi)核函數(shù)入口地址。接著,就調(diào)用函數(shù),等返回后,做一些系統(tǒng)檢查,最后返回到進(jìn)程(如果這個(gè)進(jìn)程時(shí)間用盡,就返回到其他進(jìn)程)。
(2)編寫新的系統(tǒng)調(diào)用程序
新的系統(tǒng)調(diào)用程序?qū)崿F(xiàn)的功能是:將一個(gè)文件中的內(nèi)容拷貝到另一個(gè)文件中。這個(gè)系統(tǒng)調(diào)用的參數(shù)是兩個(gè)char*型的字符指針SourceFile、GoalFile,分別表示源文件和目標(biāo)文件的路徑名。用戶進(jìn)程中的open、read、write、close函數(shù)此時(shí)對(duì)應(yīng)內(nèi)核函數(shù) sys_open、sys_read、sys_write、sys_close函數(shù)。循環(huán)拷貝的判斷條件還是
sys_read的返回值,當(dāng)其大于0的時(shí)候執(zhí)行循環(huán),否則表示源文件已拷貝到了目標(biāo)文件。
mm_segment_t類型的變量fs的作用是在讀寫文件前得到當(dāng)前fs,避免使用的緩沖區(qū)超過了用戶空間的地址范圍而報(bào)錯(cuò)。
詳細(xì)代碼見4.2.3。(3)編譯內(nèi)核 ①下載并解壓內(nèi)核
先到Linux官方網(wǎng)站http://004km.cntl.h> #define BUFFER_SIZE 102400 int main(void){ int dev,i=0;char c;
char source[BUFFER_SIZE];//寫入MyDeviceDriver設(shè)備的內(nèi)容
char goal[BUFFER_SIZE];//MyDeviceDriver設(shè)備的內(nèi)容讀入到該goal中
printf(“input the string you want to write in your device:n”);while((c=getchar())!='n')
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
{
source[i++]=c;} printf(“n”);
if((dev=open(“/dev/MyDeviceDriver”,O_RDWR))==-1)//打開MyDeviceDriver設(shè)備失敗
printf(“FAIL to open MyDeviceDriver!n”);else//成功
printf(“SUCCESS to open MyDeviceDriver!n”);
printf(“source:n%snn”,source);
write(dev,source,sizeof(source));//把source中的內(nèi)容寫入MyDeviceDriver設(shè)備
lseek(dev,0,SEEK_SET);//把文件指針定位到文件開始的位置
read(dev,goal,sizeof(source));//把MyDeviceDriver設(shè)備中的內(nèi)容讀入到goal中
printf(“goal:n%snn”,goal);
return 0;} 4.4 實(shí)驗(yàn)四
實(shí)驗(yàn)四有兩個(gè)選做題目,分別是proc文件監(jiān)控系統(tǒng)和小型文件系統(tǒng),本次實(shí)驗(yàn)我選擇的題目是proc文件監(jiān)控系統(tǒng)。4.4.1 實(shí)驗(yàn)要求
了解/proc文件的特點(diǎn)和使用方法;監(jiān)控系統(tǒng)狀態(tài),顯示系統(tǒng)中若干部件使用狀態(tài);用圖形界面實(shí)現(xiàn)系統(tǒng)監(jiān)控狀態(tài)。4.4.2 具體實(shí)現(xiàn)
(1)/proc文件系統(tǒng)的特點(diǎn)
Linux的PROC文件系統(tǒng)是進(jìn)程文件系統(tǒng)和內(nèi)核文件系統(tǒng)的組成的復(fù)合體,是將內(nèi)核數(shù)據(jù)對(duì)象化為文件形式進(jìn)行存取的一種內(nèi)存文件系統(tǒng),是監(jiān)控內(nèi)核的一種用戶接口。它擁有一些特殊的文件(純文本),從中可以獲取系統(tǒng)狀態(tài)信息。(2)功能清單
①獲取并顯示主機(jī)名,與之相關(guān)的proc文件為/proc/sys/kernel/hostname; ②獲取并顯示系統(tǒng)啟動(dòng)的時(shí)間,與之相關(guān)的proc文件為/proc/uptime; ③顯示系統(tǒng)到目前為止持續(xù)運(yùn)行的時(shí)間,與之相關(guān)的proc文件為/proc/uptime; ④顯示系統(tǒng)的版本號(hào),與之相關(guān)的proc文件為/proc/sys/kernel/ostype和/proc/sys/kernel/osrelease;
⑤ 顯示CPU的型號(hào)和主頻大小,與之相關(guān)的proc文件為/proc/cpuinfo;
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
⑥通過pid或者進(jìn)程名查詢一個(gè)進(jìn)程,并顯示該進(jìn)程的詳細(xì)信息,提供殺掉該進(jìn)程的功能,與之相關(guān)的proc文件為/proc/(pid)/stat;
⑦顯示系統(tǒng)所有進(jìn)程的一些信息,包括pid、ppid、占用內(nèi)存大小、優(yōu)先級(jí)等,與之相關(guān)的proc文件為/proc/(pid)/stat,/proc/(pid)/statm;
⑧CPU使用率的圖形化顯示(2分鐘內(nèi)的歷史記錄曲線),與之相關(guān)的proc文件為/proc/stat;
⑨內(nèi)存和交換分區(qū)的使用率的圖形化顯示(2分鐘內(nèi)的歷史曲線),與之有關(guān)的proc文件為/proc/meminfo;
⑩在狀態(tài)欄顯示當(dāng)前時(shí)間,未使用到/proc中的文件;
?在狀態(tài)欄顯示當(dāng)前CPU使用率,與之相關(guān)的proc文件為/proc/stat; ?在狀態(tài)欄顯示當(dāng)前內(nèi)存使用情況,與之相關(guān)的proc文件為/proc/meminfo; ?用新線程運(yùn)行一個(gè)其他程序,未使用到/proc中的文件; ?關(guān)機(jī)功能,未使用到/proc中的文件;(3)功能實(shí)現(xiàn)
①獲取并顯示主機(jī)名
用fopen函數(shù)打開/proc/sys/kernel/hostname文件,然后以文件指針為輸入流,用fgets從其中讀出一行字符包含主機(jī)名,然后用格式化輸出函數(shù)sscanf函數(shù)輸出一個(gè)字符串,即主機(jī)名。
②獲取并顯示系統(tǒng)啟動(dòng)的時(shí)間
從文件/proc/uptime中獲取系統(tǒng)啟動(dòng)到現(xiàn)在的運(yùn)行時(shí)間(單位是s),然后調(diào)用time函數(shù)獲取系統(tǒng)當(dāng)前時(shí)間(單位是s),用當(dāng)前時(shí)間秒數(shù)減去運(yùn)行時(shí)間秒數(shù)即為系統(tǒng)啟動(dòng)的時(shí)間秒數(shù),然后調(diào)用localtime函數(shù)將系統(tǒng)啟動(dòng)時(shí)間秒數(shù)轉(zhuǎn)換成tm結(jié)構(gòu)體類型的變量,該變量中的成員包括年份、月份、日期、星期幾、時(shí)、分、秒等,再調(diào)用輸出函數(shù)輸出即可。
③顯示系統(tǒng)到目前為止持續(xù)運(yùn)行的時(shí)間
用fopen函數(shù)打開/proc/uptime文件,然后以文件指針為輸入流,用fgets從其中讀出一行字符包含系統(tǒng)運(yùn)行時(shí)間,然后用格式化輸入函數(shù)sscanf從讀取出的字符流中輸入一個(gè)float類型的數(shù)到runtime,即系統(tǒng)運(yùn)行的時(shí)間。
④顯示系統(tǒng)的版本號(hào)
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
從/proc/sys/kernel/ostype和/proc/sys/kernel/osrelease中讀取系統(tǒng)類型(比如linux)和系統(tǒng)內(nèi)核版本號(hào),處理方法和獲取系統(tǒng)運(yùn)行時(shí)間的方法一樣。得到系統(tǒng)類型和系統(tǒng)內(nèi)核版本號(hào)之后,調(diào)用QString類的方法arg將兩個(gè)字符串連接起來,再輸出顯示即可。
⑤顯示CPU的型號(hào)和主頻大小
打開/proc/cpuinfo文件后發(fā)現(xiàn)CPU有四個(gè),相同的型號(hào),不同的主頻,后來才弄清楚所謂的四個(gè)CPU是CPU的四個(gè)核心,而“主頻”并不是主頻,而是當(dāng)前時(shí)刻該核心所使用的CPU核心頻率,隨時(shí)間而變化的。
弄清楚文件中的內(nèi)容的含義之后,開始處理/proc/cpuinfo,從中讀取CPU的型號(hào)和頻率。處理這個(gè)文件沒有用到fopen等函數(shù),而是使用了Qt自帶的兩個(gè)類QFile和QTextStream,定義一個(gè)QFile類型的變量file,并用路徑名“/proc/cpuinfo”初始化該變量,其作用是以只讀方式打開文件/proc/cpuinfo,然后以file的地址作為參數(shù)初始化QTextStream類型的變量stream,其作用是將/proc/cpuinfo文件中的內(nèi)容以字符流的形式存入變量stream中,相當(dāng)于一個(gè)文本流。由于CPU的型號(hào)是一樣的,所以只讀取第一個(gè)型號(hào)名稱即可,根據(jù)CPU型號(hào)名稱所在的行,采用while循環(huán)讀取stream中的內(nèi)容,每次讀取一行,當(dāng)行數(shù)等于CPU型號(hào)所在行時(shí),將讀取出的一行賦值給一個(gè)QString類型的變量,再調(diào)用QString的方法mid截取CPU型號(hào)名稱,file.close()關(guān)閉file。CPU四個(gè)核心的主頻處理方法和CPU型號(hào)的處理方法一致,參照上述步驟即可。
⑥通過pid或者進(jìn)程名查詢一個(gè)進(jìn)程,并顯示該進(jìn)程的詳細(xì)信息,提供殺掉該進(jìn)程的功能
在獲取所有進(jìn)程信息的時(shí)候,獲取到的所有信息已經(jīng)被存儲(chǔ)在一個(gè)全局結(jié)構(gòu)體數(shù)組變量中了,所以查詢的時(shí)候,先獲取輸入lineEdit中的文本(QString類型),然后將文本與全局結(jié)構(gòu)體數(shù)組變量的每一個(gè)數(shù)組元素的name成員和pid成員作比較,若相等,說明待查詢的進(jìn)程存在,將該進(jìn)程的詳細(xì)信息輸出即可。
殺死進(jìn)程前先要獲取將要被殺死進(jìn)程的名稱或者pid,而且該進(jìn)程必須存在于/proc目錄下,即先查詢一次待殺死的進(jìn)程,處理方法如上所述。Linux系統(tǒng)提供了kill、pkill等殺死進(jìn)程的命令,pkill通過pid殺死進(jìn)程,kill通過進(jìn)程名稱殺死進(jìn)程。通過將lineEdit中的內(nèi)容和kill或pkill組成終端命令,然后調(diào)用system函數(shù)執(zhí)行這
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
些命令即可殺死相應(yīng)的進(jìn)程。
⑦顯示系統(tǒng)所有進(jìn)程的一些信息,包括pid、ppid、占用內(nèi)存大小、優(yōu)先級(jí)等 系統(tǒng)的進(jìn)程眾多,且進(jìn)程號(hào)從1到幾萬的都有,如果從1開始遍歷訪問,效率就會(huì)很低。所以本次實(shí)驗(yàn)我采用的是Linux中對(duì)目錄進(jìn)行操作的函數(shù)opendir(),readdir()。這兩個(gè)目錄操作函數(shù)在上學(xué)期的操作系統(tǒng)第三次課程實(shí)驗(yàn)中已經(jīng)學(xué)習(xí)使用過,所以再次使用沒遇到多大的障礙。
實(shí)現(xiàn)思路為:聲明一個(gè)DIR類型的指針dir,用opendir函數(shù)打開/proc目錄,返回值賦值給dir,然后將dir作為函數(shù)readdir的參數(shù),readdir函數(shù)返回值復(fù)制給dirent結(jié)構(gòu)體指針ptr。ptr指向的結(jié)構(gòu)體包含d_name char數(shù)組成員,即文件或者目錄名,將d_name數(shù)組的0號(hào)元素分別和字符?1?、?9?比較,若處于這兩者之間,則表明該文件或者目錄是進(jìn)程目錄,以該目錄名為參數(shù)調(diào)用獲取進(jìn)程詳細(xì)信息的函數(shù)read_proc。在read_proc函數(shù)中,使用格式化輸出函數(shù)sprintf將參數(shù)目錄名c_pid對(duì)應(yīng)目錄下的文件stat的路徑輸出到char數(shù)組filename中,再調(diào)用C++的類ifstream,聲明一個(gè)ifstream類性的變量meminfo,用filename初始化meminfo,然后用析取器(>>)從meminfo中輸入數(shù)據(jù)到結(jié)構(gòu)體數(shù)組procInfo的每個(gè)元素的成員變量中,析取器(>>)會(huì)自動(dòng)忽略空字符。所需要的進(jìn)程信息并不是連續(xù)存放在stat文件中的,中間包含有其他不需要顯示的進(jìn)程信息,解決方法是定義一個(gè)string類型的變量temp,根據(jù)stat文件中的信息存放順序,將所有不需要的進(jìn)程信息全部輸入到temp中。此外還要注意一個(gè)問題,進(jìn)程名稱帶有括號(hào)“()”,所以需要將括號(hào)去掉,解決方法是使用string類的方法substr,該函數(shù)的參數(shù)有兩個(gè),一個(gè)是想截取的字符串首字符在原字符串中的位置,第二個(gè)參數(shù)是想截取的字符串末尾字符后面一個(gè)字符,在這里就是“)”。處理完畢之后,所需要的關(guān)于進(jìn)程c_pid的詳細(xì)信息都存儲(chǔ)在全局結(jié)構(gòu)體數(shù)組procInfo的元素中了。
循環(huán)采用上述思路,直到所有進(jìn)程目錄都被處理完畢,所有的進(jìn)程信息就都存儲(chǔ)在了全局結(jié)構(gòu)體數(shù)組procInfo中,然后用定時(shí)器觸發(fā)定時(shí)更新全局結(jié)構(gòu)體數(shù)組procInfo中的內(nèi)容。
⑧CPU使用率的圖形化顯示
由于需要畫出CPU使用率兩分鐘內(nèi)的歷史記錄曲線,所以需要計(jì)算并存儲(chǔ)120個(gè)連續(xù)時(shí)刻的CPU利用率。定義一個(gè)全局QList變量yList,用于存放CPU使用率。
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
在CPURate函數(shù)中調(diào)用add_point函數(shù),add_point的參數(shù)是cpuRate。在函數(shù)add_point中,首先判斷yList的大小,若大于120,則把yList的隊(duì)首元素刪除,保證yList的元素個(gè)數(shù)恒等于120;若等于0,則將yList前119個(gè)元素初始化為0,這樣的話,CPU歷史記錄曲線就會(huì)從右邊向左邊逐漸顯示出來;若大于等于1,則在yList末尾插入新的cpuRate,然后調(diào)用UpdateCPULine函數(shù)畫出記錄曲線。
得到CPU使用率之后,在函數(shù)UpdateCPULine中畫圖。先在QPixmap類型的變量pix上畫曲線,pix相當(dāng)于一塊畫布,然后再把pix添加到label標(biāo)簽上。pix的背景色設(shè)置為藍(lán)色,然后定義一個(gè)QPainter類painter,painter的畫圖設(shè)備就是pix,定義QPen畫筆pen,畫筆顏色設(shè)置為紅色,畫筆寬度為2個(gè)像素,設(shè)置完成后,以yList中存儲(chǔ)的cpuRate為縱坐標(biāo),以yList的元素下標(biāo)為橫坐標(biāo),并根據(jù)坐標(biāo)軸單位長(zhǎng)度所占實(shí)際像素個(gè)數(shù)稍微調(diào)整一下每個(gè)點(diǎn)的橫縱坐標(biāo),然后調(diào)用painter的drawLine方法畫出這些點(diǎn)并依次連接起來,就得到了2分鐘內(nèi)的CPU使用率歷史記錄曲線,而且歷史記錄曲線可以隨著時(shí)間從右向左更新。
⑨內(nèi)存和交換分區(qū)的使用率的圖形化顯示
由于需要畫出內(nèi)存使用率兩分鐘內(nèi)的歷史記錄曲線,所以需要計(jì)算并存儲(chǔ)120個(gè)連續(xù)時(shí)刻的內(nèi)存利用率。定義一個(gè)全局QList變量yList1,用于存放內(nèi)存使用率。在MemRate函數(shù)中調(diào)用add_point函數(shù),add_point的參數(shù)是memRate。在函數(shù)add_point中,首先判斷yList1的大小,若大于120,則把yList1的隊(duì)首元素刪除,保證yList1的元素個(gè)數(shù)恒等于120;若等于0,則將yList1前119個(gè)元素初始化為0,這樣的話,內(nèi)存使用率歷史記錄曲線就會(huì)從右邊向左邊逐漸顯示出來;若大于等于1,則在yList1末尾插入新的memRate,然后調(diào)用UpdateMemLine函數(shù)畫出記錄曲線。
得到內(nèi)存使用率之后,在函數(shù)UpdateMemLine中畫圖。先在QPixmap類型的變量pix上畫曲線,pix相當(dāng)于一塊畫布,然后再把pix添加到label標(biāo)簽上。pix的背景色設(shè)置為藍(lán)色,然后定義一個(gè)QPainter類painter,painter的畫圖設(shè)備就是pix,定義QPen畫筆pen,畫筆顏色設(shè)置為紅色,畫筆寬度為2個(gè)像素,設(shè)置完成后,以yList1中存儲(chǔ)的memRate為縱坐標(biāo),以yList1的元素下標(biāo)為橫坐標(biāo),并根據(jù)坐標(biāo)軸單位長(zhǎng)度所占實(shí)際像素個(gè)數(shù)稍微調(diào)整一下每個(gè)點(diǎn)的橫縱坐標(biāo),然后調(diào)用painter的drawLine方法畫出這些點(diǎn)并依次連接起來,就得到了2分鐘內(nèi)的內(nèi)存使用率歷史記
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
錄曲線,而且歷史記錄曲線可以隨著時(shí)間從右向左更新。
⑩在狀態(tài)欄顯示當(dāng)前時(shí)間
調(diào)用QDateTime的方法currentDateTime獲取當(dāng)前時(shí)間time,time是一個(gè)QDateTime類型的變量,然后調(diào)用QDateTime的方法toString把time轉(zhuǎn)化成格式為yyyy-MM-dd hh:mm:ss dddd的QString字符串,再在主窗口的狀態(tài)欄顯示輸出即可。?在狀態(tài)欄顯示當(dāng)前CPU使用率
CPU的使用率是指CPU的使用時(shí)間和CPU總時(shí)間的比值。因?yàn)?proc/stat文件中的所有值都是從系統(tǒng)啟動(dòng)開始累計(jì)到當(dāng)前時(shí)刻,所以計(jì)算CPU使用率時(shí)需要取兩個(gè)采樣點(diǎn),利用兩個(gè)點(diǎn)的差值計(jì)算CPU使用率,此次實(shí)驗(yàn)采樣方法是每隔1秒采樣一次。CPU使用率的計(jì)算公式為cpuRate=100.0-(idle2-idle1)*100.0/(total2-total1)。定義一個(gè)全局結(jié)構(gòu)體CPU_USE,具體定義如下:
typedef struct CPU_USE {
char name[16];//cpu
unsigned int user;
unsigned int nice;
unsigned int system;
unsigned int idle;
unsigned int iowait;
unsigned int irq;
unsigned int softirq;}cpu_use;CPU總時(shí)間的值等于結(jié)構(gòu)體CPU_USE中7個(gè)unsigned int類型的成員值之和。計(jì)算之前,調(diào)用get_cpu_use_stat函數(shù)獲取一個(gè)CPU狀態(tài),sleep一秒后再調(diào)用該函數(shù)獲取第二個(gè)CPU狀態(tài),然后用上述CPU使用率計(jì)算公式計(jì)算即可。
?在狀態(tài)欄顯示當(dāng)前內(nèi)存使用情況
內(nèi)存使用率是指已使用的內(nèi)存和總內(nèi)存的比值。內(nèi)存使用率的計(jì)算公式為:memRate=(total –(free+buffers+cached))*100.0/total。
定義一個(gè)全局結(jié)構(gòu)體MEM_USE,具體定義如下:
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
typedef struct MEM_USE{
unsigned long total;
unsigned long free;
unsigned long buffers;
unsigned long cached;}mem_use;該結(jié)構(gòu)體中的成員的值都來自文件/proc/meminfo,聲明一個(gè)ifstream類性的變量meminfo,用/proc/meminfo初始化meminfo,然后用析取器(>>)從meminfo中輸入數(shù)據(jù)到結(jié)構(gòu)體mem_use 的成員變量中,析取器(>>)會(huì)自動(dòng)忽略空字符。所需要的內(nèi)存數(shù)據(jù)信息并不是連續(xù)存放在/proc/meminfo文件中的,中間包含有其他不需要的內(nèi)存數(shù)據(jù)信息,解決方法是定義一個(gè)string類型的變量str,根據(jù)/proc/meminfo文件中的信息存放順序,將所有不需要的內(nèi)存數(shù)據(jù)信息全部輸入到str中。得到內(nèi)存使用的數(shù)據(jù)信息之后,使用上述內(nèi)存使用率計(jì)算公式計(jì)算即可。?用新線程運(yùn)行一個(gè)其他程序
在主窗口中添加一個(gè)lineEdit控件,獲取該控件中輸入的程序名稱,然后調(diào)用QProcess類的start方法運(yùn)行該程序。?關(guān)機(jī)功能
由于關(guān)機(jī)功能需要輸入密碼獲取root權(quán)限,所以需要想方法在點(diǎn)擊關(guān)機(jī)按鈕后輸入密碼。定義一個(gè)QString類型的變量passWord,調(diào)用類QInputDialog的方法getText,會(huì)彈出一個(gè)對(duì)話框提示輸入密碼,該方法的返回值即為密碼,將返回值賦值給passWord變量;當(dāng)對(duì)話框的OK按鈕被點(diǎn)擊時(shí),用QString(“echo %1 | sudo-S shutdown-h now”).arg(passWord)初始化QString類型的變量sudo,再把sudo轉(zhuǎn)換成char*類型,然后調(diào)用system函數(shù)執(zhí)行關(guān)機(jī)命令。(4)界面設(shè)計(jì)
新建一個(gè)Qt Widgets Application工程,用setWindowTitle函數(shù)將主窗口的標(biāo)題改為“proc進(jìn)程管理器”,設(shè)置窗口的初始大小為(650,500),初始位置為顯示屏左上角,即坐標(biāo)原點(diǎn)。
在主窗口底部添加一個(gè)狀態(tài)欄控件,用QStatusBar實(shí)現(xiàn)。狀態(tài)欄中添加三個(gè)標(biāo)簽和一個(gè)按鈕,三個(gè)標(biāo)簽分別用于顯示當(dāng)前時(shí)間、CPU使用率、內(nèi)存使用率,這三
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
個(gè)信息的顯示函數(shù)都與定時(shí)器QTimer綁定,隨時(shí)間自動(dòng)更新,按鈕用于觸發(fā)關(guān)機(jī)函數(shù)。
在主窗口的窗體中添加tabWidget控件,設(shè)置四個(gè)tab選項(xiàng)卡tab_
1、tab_
2、tab_
3、tab_4。tab_1選項(xiàng)卡用于顯示主機(jī)名、系統(tǒng)啟動(dòng)時(shí)間、系統(tǒng)運(yùn)行時(shí)間、系統(tǒng)版本號(hào)、CPU型號(hào)和主頻等信息,這些內(nèi)容全部用QLabel類的標(biāo)簽顯示,其中系統(tǒng)運(yùn)行時(shí)間和CPU主頻函數(shù)是槽函數(shù),都和定時(shí)器QTimer綁定,隨著時(shí)間自動(dòng)更新。tab_2選項(xiàng)卡用于顯示進(jìn)程詳細(xì)信息,進(jìn)程詳細(xì)信息包括進(jìn)程名、pid、ppid、內(nèi)存占用和優(yōu)先級(jí),這些信息用tableWidget控件顯示,tableWidget控件設(shè)置為禁止選中、禁止修改,tableWidget的列數(shù)是固定的5列,行數(shù)動(dòng)態(tài)確定,由獲取所有進(jìn)程詳細(xì)信息的函數(shù)get_pid_info的返回值提供;這樣做的好處是,當(dāng)創(chuàng)建新進(jìn)程或者殺死進(jìn)程時(shí),tableWidget不會(huì)出現(xiàn)行數(shù)不夠或者有空行的情況,并且ProcessInfo函數(shù)(即控制顯示進(jìn)程信息的函數(shù))與QTimer綁定,隨時(shí)間定時(shí)更新。tab_3選項(xiàng)卡用于提供查詢進(jìn)程、殺死進(jìn)程、創(chuàng)建新進(jìn)程的操作面板,查詢進(jìn)程的輸入框用lineEdit控件實(shí)現(xiàn),該控件的好處是可以直接調(diào)用控件所包含的方法text獲取輸入框的內(nèi)容,便于查詢進(jìn)程信息;在lineEdit下方放置的是tableWidget控件,同樣,該控件禁止選中、禁止修改,用于顯示查詢的進(jìn)程詳細(xì)信息;tableWidget控件下方是關(guān)閉進(jìn)程的按鈕,當(dāng)點(diǎn)擊該按鈕時(shí)便會(huì)觸發(fā)killProcess函數(shù)關(guān)閉進(jìn)程;創(chuàng)建進(jìn)程的進(jìn)程名輸入框同樣也是用lineEdit控件實(shí)現(xiàn),當(dāng)點(diǎn)擊“運(yùn)行”按鈕時(shí)便會(huì)觸發(fā)CreateProcess函數(shù)。tab_4選項(xiàng)卡用于顯示CPU使用率歷史記錄曲線和內(nèi)存使用率歷史記錄曲線。(5)程序運(yùn)行結(jié)果
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
4.4.3 源代碼
#mainwindow.h,包含各種槽函數(shù)
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include
Q_OBJECT
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();private:
Ui::MainWindow *ui;private:
QPushButton* shutButton;
QLabel* NowTimeLabel;
QLabel* CPUUseLabel;
QLabel* MemUseLabel;
QTabWidget* tabwidget;
QList
QList
void init_StatusBar();
void HostName();
void BootTime();
void OSType();
void add_point(float cpuRate);
void UpdateCPULine();
void add_point_mem(float memRate);
void UpdateMemLine();private slots:
void NowTime();
void CPURate();
void MemRate();
void run_time();
void CPUInfo();
void ProcessInfo();
void QueryProcess();
void PasswordToShutdown();
void KillProcess();
void CreateProcess();};#endif // MAINWINDOW_H
#sys.h,獲取主機(jī)名、系統(tǒng)運(yùn)行時(shí)間、系統(tǒng)版本號(hào)
#ifndef SYS #define SYS #include
FILE* fp;
char host[8];
char *hostname;
hostname=(char*)malloc(7*sizeof(char));
fp=fopen(“/proc/sys/kernel/hostname”,“r”);
fgets(host,sizeof(host),fp);
sscanf(host,“%s”,hostname);
fclose(fp);
return hostname;} float get_run_time_sec()
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
{
FILE* fp;
float runTime;
char time[32];
fp=fopen(“/proc/uptime”,“r”);
fgets(time,sizeof(time),fp);
sscanf(time,“%f”,&runTime);
fclose(fp);
return runTime;} QString get_os_type(){
QString os;
char ostype[6],osrelease[8];
char buff1[16],buff2[16];
FILE *fp1,*fp2;
fp1=fopen(“/proc/sys/kernel/ostype”,“r”);
fp2=fopen(“/proc/sys/kernel/osrelease”,“r”);
fgets(buff1,sizeof(buff1),fp1);
fgets(buff2,sizeof(buff2),fp2);
sscanf(buff1,“%s”,ostype);
sscanf(buff2,“%s”,osrelease);
os=QString(“%1 %2”).arg(ostype).arg(osrelease);
fclose(fp1);
fclose(fp2);
return os;} #endif // SYS
#process.h,獲取所有進(jìn)程詳細(xì)信息
#ifndef PROCESS #define PROCESS #include
string name;
string pid;
string ppid;
string rss;
string priority;}procInfo[40960];void read_proc(PROC_INFO *pidinfo,const char *c_pid){
string temp,pidname;
char filename[18];
sprintf(filename,“/proc/%s/stat”,c_pid);
std::ifstream meminfo(filename);
meminfo>>(pidinfo->pid)>>pidname>>temp>>(pidinfo->ppid)>>temp>>temp;
meminfo>>temp>>temp>>temp>>temp>>temp>>temp;
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
meminfo>>temp>>temp>>temp>>temp>>temp>>(pidinfo->priority);
meminfo>>temp>>temp>>temp>>temp>>temp>>(pidinfo->rss);
pidinfo->name=pidname.substr(1,pidname.find(')')-1);//remove“()”
meminfo.close();} int get_pid_info(){
DIR *dir;
struct dirent *ptr;
int i=0;
if(!(dir=opendir(“/proc”)))
return 0;
while((ptr=readdir(dir))!=false)
{
if(ptr->d_name[0]>='1' && ptr->d_name[0]<='9')
{
read_proc(&(procInfo[i]),ptr->d_name);
i++;
}
}
closedir(dir);
return i;} #endif // PROCESS
#mem.h,計(jì)算內(nèi)存使用率
#ifndef MEM #define MEM #include
unsigned long total;
unsigned long free;
unsigned long buffers;
unsigned long cached;}mem_use;void get_mem_use_stat(mem_use *memStat){
string str;
unsigned long memtotal,memfree,memavailable,membuffers,memcached;
std::ifstream meminfo(“/proc/meminfo”);
meminfo>>str>>memtotal>>str;
meminfo>>str>>memfree>>str;
meminfo>>str>>memavailable>>str;
meminfo>>str>>membuffers>>str;
meminfo>>str>>memcached>>str;
(*memStat).total=memtotal;
(*memStat).free=memfree;
(*memStat).buffers=membuffers;
(*memStat).cached=memcached;
meminfo.close();
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
} float clacu_memRate(mem_use *memStat){
float memRate=0.0;
memRate=(float)(((*memStat).totalruntime;
ptm = localtime(&boot_time);
boot=QString(“%1-%2-%3 %4:%5:%6 %7”).arg(ptm->tm_year+1900).arg(ptm->tm_mon+1).arg(ptm->tm_mday).arg(ptm->tm_hour).arg(ptm->tm_min).arg(ptm->tm_sec).arg(week[ptm->tm_wday]);
ui->bootlabel->setText(boot);} void MainWindow::OSType(){
QString os;
os=get_os_type();
ui->ostypelabel->setText(os);} void MainWindow::PasswordToShutdown(){
QString passWord;
QString sudo;
char* command;
bool OK;
QByteArray ba;
passWord=QInputDialog::getText(this,“輸入密碼”,“輸入密碼”,QLineEdit::Normal,“",&OK);
if(OK)
{
sudo=QString(”echo %1 | sudo-S shutdown-h now“).arg(passWord);
ba=sudo.toLatin1();
command=ba.data();
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
system(command);
} } void MainWindow::CPUInfo(){
QString processor;
QString Hz0,Hz1,Hz2,Hz3;
processor=get_processor();
ui->processorlabel0->setText(QString(”0: %1“).arg(processor));
ui->processorlabel1->setText(QString(”1: %1“).arg(processor));
ui->processorlabel2->setText(QString(”2: %1“).arg(processor));
ui->processorlabel3->setText(QString(”3: %1“).arg(processor));
Hz0=get_Hz0();
Hz0=QString(”%1%2“).arg(Hz0).arg(”MHz“);
ui->Hzlabel0->setText(Hz0);
Hz1=get_Hz1();
Hz1=QString(”%1%2“).arg(Hz1).arg(”MHz“);
ui->Hzlabel1->setText(Hz1);
Hz2=get_Hz2();
Hz2=QString(”%1%2“).arg(Hz2).arg(”MHz“);
ui->Hzlabel2->setText(Hz2);
Hz3=get_Hz3();
Hz3=QString(”%1%2“).arg(Hz3).arg(”MHz“);
ui->Hzlabel3->setText(Hz3);} void MainWindow::ProcessInfo(){
int pidNum;
int i;
QStringList headers;
QTableWidgetItem *nameItem;
QTableWidgetItem *pidItem;
QTableWidgetItem *ppidItem;
QTableWidgetItem *rssItem;
QTableWidgetItem *priorityItem;
pidNum=get_pid_info();
ui->tableWidget->setColumnCount(5);
ui->tableWidget->setRowCount(pidNum);
headers<<”進(jìn)程名“<<”pid“<<”ppid“<<”內(nèi)存占用/KB“<<”優(yōu)先級(jí)“;
ui->tableWidget->setHorizontalHeaderLabels(headers);
for(i=0;i
{
nameItem=new QTableWidgetItem(QString::fromStdString(procInfo[i].name));
ui->tableWidget->setItem(i,0,nameItem);
nameItem->setTextAlignment(Qt::AlignCenter);
pidItem=new QTableWidgetItem(QString::fromStdString(procInfo[i].pid));
ui->tableWidget->setItem(i,1,pidItem);
pidItem->setTextAlignment(Qt::AlignCenter);
ppidItem=new QTableWidgetItem(QString::fromStdString(procInfo[i].ppid));
ui->tableWidget->setItem(i,2,ppidItem);
ppidItem->setTextAlignment(Qt::AlignCenter);
rssItem=new QTableWidgetItem(QString::fromStdString(procInfo[i].rss));
ui->tableWidget->setItem(i,3,rssItem);
rssItem->setTextAlignment(Qt::AlignCenter);
priorityItem=new QTableWidgetItem(QString::fromStdString(procInfo[i].priority));
ui->tableWidget->setItem(i,4,priorityItem);
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
priorityItem->setTextAlignment(Qt::AlignCenter);
}
ui->tableWidget->setColumnWidth(0,121);
ui->tableWidget->setColumnWidth(1,121);
ui->tableWidget->setColumnWidth(2,121);
ui->tableWidget->setColumnWidth(3,121);
ui->tableWidget->setColumnWidth(4,121);
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableWidget->setSelectionMode(QAbstractItemView::NoSelection);} void MainWindow::QueryProcess(){
QString queryitem;
int pidNum,i;
QStringList headers;
QTableWidgetItem *nameItem;
QTableWidgetItem *pidItem;
QTableWidgetItem *ppidItem;
QTableWidgetItem *rssItem;
QTableWidgetItem *priorityItem;
QHeaderView* headerView = ui->tableWidget_2->verticalHeader();
headerView->setHidden(true);//no row number
queryitem=ui->lineEdit->text();
pidNum=get_pid_info();
for(i=0;i
{
if(queryitem==QString::fromStdString(procInfo[i].name)|| queryitem==QString::fromStdString(procInfo[i].pid))
break;
}
ui->tableWidget_2->setColumnCount(5);
ui->tableWidget_2->setRowCount(1);
headers<<”進(jìn)程名“<<”pid“<<”ppid“<<”內(nèi)存占用/KB“<<”優(yōu)先級(jí)“;
ui->tableWidget_2->setHorizontalHeaderLabels(headers);
nameItem=new QTableWidgetItem(QString::fromStdString(procInfo[i].name));
ui->tableWidget_2->setItem(0,0,nameItem);
nameItem->setTextAlignment(Qt::AlignCenter);
pidItem=new QTableWidgetItem(QString::fromStdString(procInfo[i].pid));
ui->tableWidget_2->setItem(0,1,pidItem);
pidItem->setTextAlignment(Qt::AlignCenter);
ppidItem=new QTableWidgetItem(QString::fromStdString(procInfo[i].ppid));
ui->tableWidget_2->setItem(0,2,ppidItem);
ppidItem->setTextAlignment(Qt::AlignCenter);
rssItem=new QTableWidgetItem(QString::fromStdString(procInfo[i].rss));
ui->tableWidget_2->setItem(0,3,rssItem);
rssItem->setTextAlignment(Qt::AlignCenter);
priorityItem=new QTableWidgetItem(QString::fromStdString(procInfo[i].priority));
ui->tableWidget_2->setItem(0,4,priorityItem);
priorityItem->setTextAlignment(Qt::AlignCenter);
ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableWidget->setSelectionMode(QAbstractItemView::NoSelection);} void MainWindow::KillProcess(){
QString queryitem;
int pidNum,i;
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
int killtype=-1;
QString sudo;
char* command;
QByteArray ba;
queryitem=ui->lineEdit->text();
pidNum=get_pid_info();
for(i=0;i
{
if(queryitem==QString::fromStdString(procInfo[i].name)|| queryitem==QString::fromStdString(procInfo[i].pid))
break;
}
if(queryitem==QString::fromStdString(procInfo[i].name))
killtype=0;
if(queryitem==QString::fromStdString(procInfo[i].pid))
killtype=1;
switch(killtype){
case 0:
sudo=QString(”pkill %1“).arg(queryitem);
ba=sudo.toLatin1();
command=ba.data();
system(command);
break;
case 1:
sudo=QString(”kill %1“).arg(queryitem);
ba=sudo.toLatin1();
command=ba.data();
system(command);
break;
default:
break;
} } void MainWindow::CreateProcess(){
QProcess *pro=new QProcess;
QString newProc;
newProc=ui->lineEdit_2->text();
pro->start(newProc);} void MainWindow::add_point(float cpuRate){
int i;
int size=yList.size();
int y=cpuRate;
if(size>120)
{
yList.pop_front();
}
if(size==0)
{
for(i=0;i<119;i++)
{
yList.push_back(0);
}
}
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
if(size>=1)
{
yList.push_back(y);
emit UpdateCPULine();
}
else{
yList.push_back(y);
} } void MainWindow::UpdateCPULine(){
int count=0;
QPixmap pix(600,160);
QPainter painter(&pix);
pix.fill(Qt::blue);
QPen pen0;
pen0.setColor(Qt::lightGray);
painter.setPen(pen0);
for(int i=1;i<4;i++)
{
painter.drawLine(0,i*40,600,i*40);
}
QPen pen;
pen.setColor(Qt::red);
pen.setWidth(2);
painter.setPen(pen);
while(count<(yList.size()-1))
{
painter.drawLine(5*count,160-1.6*(yList.value(count)),5*(count+1),160-1.6*(yList.value(count+1)));
count++;
}
ui->cpuline_label->setPixmap(pix);} void MainWindow::add_point_mem(float memRate){
int i;
int size=yList1.size();
int y=memRate;
if(size>120)
{
yList1.pop_front();
}
if(size==0)
{
for(i=0;i<119;i++)
{
yList1.push_back(0);
}
}
if(size>=1)
{
yList1.push_back(y);
emit UpdateMemLine();
}
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告
else{
yList1.push_back(y);
} } void MainWindow::UpdateMemLine(){
int count=0;
QPixmap pix(600,160);
QPainter painter(&pix);
pix.fill(Qt::blue);
QPen pen0;
pen0.setColor(Qt::lightGray);
painter.setPen(pen0);
for(int i=1;i<4;i++)
{
painter.drawLine(0,i*40,600,i*40);
}
QPen pen;
pen.setColor(Qt::red);
pen.setWidth(2);
painter.setPen(pen);
while(count<(yList1.size()-1))
{ painter.drawLine(5*count,160-1.6*(yList1.value(count)),5*(count+1),160-1.6*(yList1.value(count+1)));
count++;
}
ui->memlinelabel->setPixmap(pix);}
#main.cpp,新建主窗口并顯示
#include ”mainwindow.h" #include
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();} 心得體會(huì)
本次課程設(shè)計(jì),第一個(gè)題目很簡(jiǎn)單,以前寫過文件拷貝的C語言程序,第一個(gè)題目在以前的基礎(chǔ)上用open、read、write等替換fopen、fread、fwrite即可;第二個(gè)題目和第三個(gè)題目是第一次遇見,在此之前對(duì)系統(tǒng)調(diào)用和設(shè)備驅(qū)動(dòng)程序的知識(shí)知之甚少,所以剛開始障礙比較大,但是慢慢地就有了些了解,也就沒那么復(fù)雜了,但是需要細(xì)心;第四個(gè)題目看起來很復(fù)雜,其實(shí)沒那么復(fù)雜,第一題已經(jīng)解決了Qt
華 中 科 技 大 學(xué) 課 程 設(shè) 計(jì) 報(bào) 告 的使用問題,剩下的就是對(duì)/proc文件系統(tǒng)的處理問題,包括文件的讀取、讀取之后對(duì)字符串的處理等,這些處理相對(duì)來說比較繁瑣,所以花費(fèi)了不少時(shí)間。
這次課設(shè)讓我對(duì)Linux的系統(tǒng)調(diào)用、設(shè)備驅(qū)動(dòng)程序的工作原理、/proc文件系統(tǒng)等有了更深的理解,對(duì)Qt的使用比以前更加熟練。總而言之,這次課設(shè)讓我收獲很多,受益匪淺。
第四篇:操作系統(tǒng)課設(shè)程序源
南京工程學(xué)院
課程設(shè)計(jì)報(bào)告
課 程 名 稱 操作系統(tǒng)原理與應(yīng)用 實(shí) 驗(yàn) 名 稱 儲(chǔ)存管理 院(系、部、中心)
通信工程學(xué)院
專
業(yè)
通信工程
班 級(jí) 信息工程111 姓 名 車含喆 學(xué) 號(hào) 208110808 起 止 日 期 2014.4.22 指 導(dǎo) 教 師 耿鵬
1、實(shí)驗(yàn)?zāi)康?/p>
1.通過模擬實(shí)現(xiàn)請(qǐng)求頁式存儲(chǔ)管理的幾種基本頁面置換算法。2.了解虛擬存儲(chǔ)技術(shù)的特點(diǎn)
3.掌握虛擬存儲(chǔ)請(qǐng)求頁式存儲(chǔ)管理中幾種基本頁面置換算法的基本思想和實(shí)現(xiàn)過程,并比較它們的效率。
2、實(shí)驗(yàn)內(nèi)容
3、實(shí)驗(yàn)設(shè)備
PC 1臺(tái),Ubuntu 操作系統(tǒng)
4、實(shí)驗(yàn)總結(jié)
UNIX中,為了提高內(nèi)存利用率,提供了內(nèi)外存進(jìn)程對(duì)換機(jī)制;內(nèi)存空間的分配和回收均以頁為單位進(jìn)行;一個(gè)進(jìn)程只需將其一部分調(diào)入內(nèi)存便可運(yùn)行;還支持請(qǐng)求調(diào)頁的儲(chǔ)存管理方式。
5.實(shí)驗(yàn)程序
#include
};typedef struct pfc_struct pfc_type;pfc_type pfc[total_vp],*freepf_head,*busypf_head,*busypf_tail;int diseffect, a[total_instruction];int page[total_instruction],offset[total_instruction];int initialize(int);int FIF0(int);int LRU(int);int LFU(int);int NUR(int);int OPT(int);int pn,pfn;struct pfc_struct *next;
int main(){ int s,j,i;srand(10*getpid());s=(float)319*rand()/32767/32767/2+1;
for(i=0;i } int initialize(total_pf)int total_pf;{ int i;diseffect=0;for(i=0;i { } for(i=0;i } return 0;LRU(i);OPT(i); } pfc[i].next=&pfc[i+1];pfc[i].pfn=i;pfc[total_pf-1].next=NULL; } int FIFO(total_pf)int total_pf;{ int i,j;pfc_type *p;initialize(total_pf);busypf_head=busypf_tail=NULL;for(i=0;i } printf(“FIFO:%6.4fn”,1-(float)diseffect/320);return 0;if(pl[page[i]].pfn==INVALID){ diseffect+=1;if(freepf_head==NULL){ p=busypf_head==NULL;pl[busypf_head->pn].pfn=INVALID;freepf_head=busypf_head;freepf_head->next=NULL;busypf_head=p;} p=freepf_head->next;freepf_head->next=NULL;freepf_head->pn=page[i];pl[page[i]].pfn=freepf_head->pfn;if(busypf_tail==NULL)busypf_head=busypf_tail=freepf_head;else { } freepf_head=p;} busypf_tail->next=freepf_head;busypf_tail=freepf_head;pfc[total_pf-1].pfn=total_pf-1;freepf_head=&pfc[0];return 0; } int LRU(total_pf)int total_pf;{ int min,minj,i,j,present_time;initialize(total_pf);present_time=0;for(i=0;i } if(pl[page[i]].pfn==INVALID){ } else pl[page[i]].time=present_time;diseffect++;if(freepf_head=NULL){ } pl[page[i]].pfn=freepf_head->pfn;pl[page[i]].time=present_time;freepf_head=freepf_head->next;min=32767;for(j=0;j if(min>pl[j].time&&pl[j].pfn!=INVALID){ } min=pl[j].time;minj=j;freepf_head=&pfc[pl[minj].pfn];pl[minj].pfn=INVALID;pl[minj].time=-1;freepf_head->next=NULL;present_time++;printf(“LRU:%6.4fn”,1-(float)diseffect/320);} int OPT(total_pf)int total_pf;{ int i,j,max,maxpage,d,dist[total_vp]; pfc_type *t;initialize(total_pf);for(i=0;i } freepf_head->next=NULL;pl[maxpage].pfn=INVALID;} diseffect++;if(freepf_head==NULL){ for(j=0;j 實(shí)驗(yàn)一 一、實(shí)驗(yàn)名稱 進(jìn)程調(diào)度的設(shè)計(jì)與實(shí)現(xiàn) 二、實(shí)驗(yàn)?zāi)康?、綜合應(yīng)用下列知識(shí)點(diǎn)設(shè)計(jì)并實(shí)現(xiàn)操作系統(tǒng)的進(jìn)程調(diào)度:鄰接表,布爾 數(shù)組,非阻塞輸入,圖形用戶界面GUI,進(jìn)程控制塊,進(jìn)程狀態(tài)轉(zhuǎn)換,多級(jí)反饋隊(duì)列進(jìn)程調(diào)度算法。 2、加深理解操作系統(tǒng)進(jìn)程調(diào)度的過程。 3、加深理解多級(jí)反饋隊(duì)列進(jìn)程調(diào)度算法。 三、實(shí)驗(yàn)內(nèi)容與主要設(shè)計(jì)思想 1、采用一種熟悉的語言,如C、PASCAL或C++等,編制程序。 2、采用多級(jí)反饋隊(duì)列調(diào)度算法進(jìn)行進(jìn)程調(diào)度。 3、每個(gè)進(jìn)程對(duì)應(yīng)一個(gè)PCB。在PCB中包括進(jìn)程標(biāo)識(shí)符pid、進(jìn)程的狀態(tài) 標(biāo)識(shí)status、進(jìn)程優(yōu)先級(jí)priority、進(jìn)程的隊(duì)列指針next和表示進(jìn)程生命周期的數(shù)據(jù)項(xiàng)life(在實(shí)際系統(tǒng)中不包括該項(xiàng))。 4、創(chuàng)建進(jìn)程時(shí)即創(chuàng)建一個(gè)PCB,各個(gè)進(jìn)程的pid都是唯一的,pid是在1 到100范圍內(nèi)的一個(gè)整數(shù)??梢詣?chuàng)建一個(gè)下標(biāo)為1到100的布爾數(shù)組,“真”表示下標(biāo)對(duì)應(yīng)的進(jìn)程標(biāo)識(shí)號(hào)是空閑的,“假”表示下標(biāo)對(duì)應(yīng)的進(jìn)程標(biāo)識(shí)號(hào)已分配給某個(gè)進(jìn)程。 5、進(jìn)程狀態(tài)status的取值為“就緒ready”或“運(yùn)行run”,剛創(chuàng)建時(shí),狀態(tài)為“ready”。被進(jìn)程調(diào)度程序選中后變?yōu)椤皉un”。 6、進(jìn)程優(yōu)先級(jí)priority是0到49范圍內(nèi)的一個(gè)隨機(jī)整數(shù)。 7、進(jìn)程生命周期life是1到5范圍內(nèi)的一個(gè)隨機(jī)整數(shù)。 8、初始化時(shí),創(chuàng)建一個(gè)鄰接表,包含50個(gè)就緒隊(duì)列,各就緒隊(duì)列的進(jìn) 程優(yōu)先級(jí)priority分別是0到49。 9、為了模擬用戶動(dòng)態(tài)提交任務(wù)的過程,要求動(dòng)態(tài)創(chuàng)建進(jìn)程。進(jìn)入進(jìn)程調(diào) 度循環(huán)后,每次按ctrl+f即動(dòng)態(tài)創(chuàng)建一個(gè)進(jìn)程,然后將該P(yáng)CB插入就緒隊(duì)列中。按ctrl+q退出進(jìn)程調(diào)度循環(huán)。 10、在進(jìn)程調(diào)度循環(huán)中,每次選擇優(yōu)先級(jí)最大的就緒進(jìn)程來執(zhí)行。將 其狀態(tài)從就緒變?yōu)檫\(yùn)行,通過延時(shí)一段時(shí)間來模擬該進(jìn)程執(zhí)行一個(gè)時(shí) 間片的過程,然后優(yōu)先級(jí)減半,生命周期減一。設(shè)計(jì)圖形用戶界面GUI,在窗口中顯示該進(jìn)程和其他所有進(jìn)程的PCB內(nèi)容。如果將該運(yùn)行進(jìn)程的生命周期不為0,則重新把它變?yōu)榫途w狀態(tài),插入就緒隊(duì)列中;否則該進(jìn)程執(zhí)行完成,撤消其PCB。以上為一次進(jìn)程調(diào)度循環(huán)。 11、在上機(jī)實(shí)現(xiàn)該程序之后,要求寫出實(shí)驗(yàn)報(bào)告,其中包括實(shí)驗(yàn)名稱、實(shí)驗(yàn)?zāi)康?、?shí)驗(yàn)內(nèi)容、程序的主要流程圖、實(shí)驗(yàn)心得和主要源程序清單等。 四、操作系統(tǒng)綜合性、設(shè)計(jì)性實(shí)驗(yàn)課程介紹 (1)課程簡(jiǎn)介與要求 《操作系統(tǒng)》是計(jì)算機(jī)專業(yè)學(xué)生的必修課程,該課程要求以計(jì)算機(jī) 組成原理、數(shù)據(jù)結(jié)構(gòu)、PASCAL語言程序設(shè)計(jì)(或C語言程序設(shè)計(jì))作為先行課程。課程的教學(xué)目標(biāo)是:使學(xué)生學(xué)習(xí)和掌握操作系統(tǒng)的主要功能、基本原理、主要算法和實(shí)施技術(shù),懂得操作系統(tǒng)在現(xiàn) 代計(jì)算機(jī)系統(tǒng)中的重要作用,具有分析實(shí)際操作系統(tǒng)的基本能力。 (2)實(shí)驗(yàn)?zāi)康募耙?/p> 鞏固和加深對(duì)操作系統(tǒng)相關(guān)知識(shí)的理解;掌握模擬的實(shí)驗(yàn)方法;提 高編程能力。 (3)實(shí)驗(yàn)方式與要求 根據(jù)在操作系統(tǒng)課程所學(xué)的理論,采用模擬的方法編程實(shí)現(xiàn)操作系 統(tǒng)的某些功能,上機(jī)調(diào)試通過,并提交實(shí)驗(yàn)報(bào)告。 (4)考試方法及評(píng)分 上機(jī)檢查與批改實(shí)驗(yàn)報(bào)告相結(jié)合,占總評(píng)成績(jī)的20%到30%。 (5)主要儀器設(shè)備 臺(tái)式電腦。 (6)教材及參考書 教材: 《計(jì)算機(jī)操作系統(tǒng)教程》張堯?qū)W等,清華大學(xué)出版社,2006年10月第3版 主要參考書: ? 《UNIX操作系統(tǒng)教程》尤晉元,西北電訊工程學(xué)院出版社,198 5年 ? 《操作系統(tǒng)》馮耀霖等,西安電子科技大學(xué)出版社,1994年 ? 《操作系統(tǒng)原理》尤晉元,上海交大出版社,1984年 ? 《計(jì)算機(jī)操作系統(tǒng)》湯子瀛等,西安電子科技大學(xué)出版社,1996年12月第一版 [附錄一]實(shí)驗(yàn)報(bào)告的格式 實(shí)驗(yàn)課程:操作系統(tǒng) 實(shí)驗(yàn)名稱:進(jìn)程調(diào)度的設(shè)計(jì)與實(shí)現(xiàn)(綜合實(shí)驗(yàn))第一部分 實(shí)驗(yàn)內(nèi)容 1.實(shí)驗(yàn)?zāi)繕?biāo) 1、綜合應(yīng)用下列知識(shí)點(diǎn)設(shè)計(jì)并實(shí)現(xiàn)操作系統(tǒng)的進(jìn)程調(diào)度:鄰接表,布爾 數(shù)組,非阻塞輸入,圖形用戶界面GUI,進(jìn)程控制塊,進(jìn)程狀態(tài)轉(zhuǎn)換,多級(jí)反饋隊(duì)列進(jìn)程調(diào)度算法。 2、加深理解操作系統(tǒng)進(jìn)程調(diào)度的過程。 3、加深理解多級(jí)反饋隊(duì)列進(jìn)程調(diào)度算法。 2.實(shí)驗(yàn)任務(wù) 1、用一種熟悉的語言,如C、PASCAL或C++等,編制程序。 2、采用多級(jí)反饋隊(duì)列調(diào)度算法進(jìn)行進(jìn)程調(diào)度。 3.實(shí)驗(yàn)設(shè)備及環(huán)境 PC;C/C++等編程語言。 4.實(shí)驗(yàn)主要步驟 (1)根據(jù)實(shí)驗(yàn)?zāi)繕?biāo),明確實(shí)驗(yàn)的具體任務(wù); (2)編寫程序?qū)崿F(xiàn)進(jìn)程調(diào)度算法; (3)設(shè)計(jì)實(shí)驗(yàn)數(shù)據(jù)并運(yùn)行程序、記錄運(yùn)行的結(jié)果; (4)分析實(shí)驗(yàn)結(jié)果; (5)實(shí)驗(yàn)后的心得體會(huì)。 第二部分 問題及算法 1.問題描述(學(xué)生填) 2.多級(jí)反饋隊(duì)列進(jìn)程調(diào)度算法的一般思路(學(xué)生填) 3.算法實(shí)現(xiàn)的關(guān)鍵點(diǎn)(學(xué)生填) 第三部分 實(shí)驗(yàn)結(jié)果與分析 1.實(shí)驗(yàn)數(shù)據(jù)及結(jié)果(學(xué)生填) 2.實(shí)驗(yàn)分析及結(jié)論(學(xué)生填) 第四部分 心得與展望 1.自我評(píng)價(jià)及心得體會(huì)(學(xué)生填) 2.展望(學(xué)生填) 第五部分 附錄 1.主要界面(學(xué)生填) 2.源程序(學(xué)生填) 參考文獻(xiàn)(學(xué)生填) 實(shí)驗(yàn)二 一、實(shí)驗(yàn)名稱 模擬操作系統(tǒng)的頁面置換 二、實(shí)驗(yàn)?zāi)康?、掌握操作系統(tǒng)的頁面置換過程,加深理解頁式虛擬存儲(chǔ)器的實(shí)現(xiàn)原理。 2、掌握用隨機(jī)數(shù)生成滿足一定條件的指令地址流的方法。 3、掌握頁面置換的模擬方法。 三、實(shí)驗(yàn)要求與提示 1、采用一種熟悉的語言,如C、PASCAL、C++或Java等,編制程序。 2、模擬操作系統(tǒng)采用OPT、FIFO和LRU算法進(jìn)行頁面置換的過程。 3、設(shè)程序中地址范圍為0到32767,采用隨機(jī)數(shù)生成256個(gè)指令地址,滿足50%的地址是順序執(zhí)行,25%向前跳,25%向后跳。為滿足上述條件,可采取下列方法:設(shè)d0=10000,第n個(gè)指令地址為dn,第n+1個(gè)指令地址為dn+1,n的取值范圍為0到255。每次生成一個(gè)1到1024范圍內(nèi)的隨機(jī)數(shù)a,如果a落在1到512范圍內(nèi),則dn+1=dn+1。如果a落在513到768范圍內(nèi),則設(shè)置dn+1為1到dn范圍內(nèi)一個(gè)隨機(jī)數(shù)。如果a落在769到1024范圍內(nèi),則設(shè)置dn+1為dn到32767范圍內(nèi)一個(gè)隨機(jī)數(shù)。 4、頁面大小的取值范圍為1K,2K,4K,8K,16K。按照頁面大小將指令地址轉(zhuǎn)化為頁號(hào)。對(duì)于相鄰相同的頁號(hào),合并為一個(gè)。 5、分配給程序的內(nèi)存塊數(shù)取值范圍為1塊,2塊,直到程序的頁面數(shù)。 6、分別采用OPT、FIFO和LRU算法對(duì)頁號(hào)序列進(jìn)行調(diào)度,計(jì)算出對(duì)應(yīng)的缺頁中斷率。 7、打印出頁面大小、分配給程序的內(nèi)存塊數(shù)、算法名、對(duì)應(yīng)的缺頁中斷率。 8、分析頁面大小和分配給程序的內(nèi)存塊數(shù)對(duì)缺頁中斷率的影響。分析不同的頁面置換算法的調(diào)度性能。 9、在上機(jī)實(shí)現(xiàn)該程序之后,要求寫出實(shí)驗(yàn)報(bào)告,其中包括實(shí)驗(yàn)名稱、實(shí)驗(yàn)?zāi)康?、?shí)驗(yàn)內(nèi)容、程序的主要流程圖、實(shí)驗(yàn)心得和主要源程序清單等。第五篇:操作系統(tǒng)本科實(shí)驗(yàn)任務(wù)