Linux 操作系统课程设计
Linux操作系統(tǒng)課程設(shè)計(jì)
中國地質(zhì)大學(xué)(武漢)計(jì)算機(jī)學(xué)院計(jì)算機(jī)科學(xué)與技術(shù)專業(yè)本科生《操作系統(tǒng)概論》課程設(shè)計(jì)(作記錄)。
1. 課程設(shè)計(jì)要求
2. 評(píng)分
3. 上機(jī)時(shí)間地點(diǎn)
- 17 周 (12 月 25-29 日)周二下午、周四下午、周五上午,晚上。
- 18 周 (元月 1-5 日)周二下午、周三下午,晚上 。
- 前 7 次地點(diǎn):12 班在 313 機(jī)房(Fedora) 34 班在 413 機(jī)房(Ubuntu)
- 最后一次上機(jī): 12 班:18 周周四 晚上 34 班:18 周周五 晚上
地點(diǎn):313 機(jī)房(Fedora) 上午 8:30-11:30 下午 2:00-5:00 晚上 6:30-9:30
開機(jī)時(shí)進(jìn)入 Linux 系統(tǒng),默認(rèn)使用用戶名:suer,密碼:123456。若默認(rèn)密碼登錄不了,可能是被同學(xué)修改過了,換一臺(tái)電腦使用。請(qǐng)同學(xué)們千萬不要修改系統(tǒng)登錄密碼。若有同學(xué)自己的筆記本電腦已經(jīng)裝了 Linux,歡迎自帶電腦上機(jī)實(shí)習(xí)。
4. 每次上機(jī)實(shí)習(xí)前先自學(xué)預(yù)備知識(shí),并在作業(yè)本上編寫初步的源程序。
5. 課程設(shè)計(jì)題目課程設(shè)計(jì)分六個(gè)實(shí)驗(yàn),具體如下
5.1 實(shí)驗(yàn) 1:作業(yè)調(diào)度
5.1.1 實(shí)驗(yàn)?zāi)康?/h3>
5.1.2 實(shí)驗(yàn)內(nèi)容
1、假設(shè)系統(tǒng)中可同時(shí)運(yùn)行兩道作業(yè),給出每道作業(yè)的到達(dá)時(shí)間和運(yùn)行時(shí)間,如下表所示:
| 到達(dá)時(shí)間 | 0 | 2 | 5 | 7 | 12 | 15 | 4 | 6 | 8 | 10 |
| 運(yùn)行時(shí)間 | 10 | 20 | 30 | 40 | 8 | 8 | 20 | 10 | 12 | 7 |
2、分別用先來先服務(wù)算法、短作業(yè)優(yōu)先和響應(yīng)比高者優(yōu)先三種算法給出作業(yè)的調(diào)度順序。
3、計(jì)算每一種算法的平均周轉(zhuǎn)時(shí)間及平均帶權(quán)周轉(zhuǎn)時(shí)間并比較不同算法的優(yōu)劣。
5.1.3 預(yù)備知識(shí)
響應(yīng)比=等待時(shí)間/運(yùn)行時(shí)間+1
周轉(zhuǎn)時(shí)間=完成時(shí)間-到達(dá)時(shí)間 帶權(quán)周轉(zhuǎn)時(shí)間=周轉(zhuǎn)時(shí)間/運(yùn)行時(shí)間
5.1.4 源代碼
#include <iostream> #include <string> #include <fstream> #include <vector>using namespace std;struct Work {char name;//作業(yè)名稱double arrive;//到達(dá)時(shí)間點(diǎn)double run;//運(yùn)行時(shí)間Work() {}Work(char n, double a, double t) :name(n), arrive(a), run(t) {}Work operator =(const Work &rhs){this->name = rhs.name;this->arrive = rhs.arrive;this->run = rhs.run;return *this;} };vector<Work> gWork;//存放所有的作業(yè)信息 double sum_turn, sum_dturn;//總的周轉(zhuǎn)時(shí)間和帶權(quán)周轉(zhuǎn)時(shí)間void ReadFile();//從txt文本中讀取作業(yè)調(diào)度信息 void Output();//輸出結(jié)果 void Dispatch();//調(diào)度過程中的數(shù)據(jù)處理 void Fcfs();//先來先服務(wù)算法 void Sjf();//短作業(yè)優(yōu)先算法 void Hrf();//高響應(yīng)比優(yōu)先算法int main() {ReadFile();cout << "先來先服務(wù)算法:" << endl;Fcfs();cout << "短作業(yè)優(yōu)先算法:" << endl;Sjf();cout << "高響應(yīng)比算法:" << endl;Hrf();return 0; }//從文本中讀取作業(yè)調(diào)度信息 void ReadFile() {ifstream ifile;ifile.open("/home/jason/文檔/OS/Pro_1/data.txt");if (!ifile){cout << "文件打開失敗!" << endl;return;}char name;double arrive;double run;while (ifile >> name >> arrive >> run){gWork.push_back(Work(name, arrive, run));}ifile.close(); }//輸出結(jié)果 void Output() {cout << "作業(yè)調(diào)度順序:";for (unsigned i = 0; i < gWork.size(); ++i)cout << gWork[i].name << " ";cout << endl;cout << "平均周轉(zhuǎn)時(shí)間:" << sum_turn / gWork.size() << endl;cout << "平均帶權(quán)周轉(zhuǎn)時(shí)間:" << sum_dturn / gWork.size() << endl;cout << endl; }//調(diào)度過程中的數(shù)據(jù)處理 void Dispatch() {unsigned n = static_cast<unsigned>(gWork.size());double t1 = 0, t2 = 0;//同時(shí)運(yùn)行兩個(gè)作業(yè),設(shè)置兩個(gè)時(shí)間軸以記錄各個(gè)作業(yè)完成情況sum_turn = 0;//初始化sum_dturn = 0;for (unsigned i = 0; i < n; ++i){if (t1 > t2)//表明t1有作業(yè)時(shí)t2空閑{if (t2 < gWork[i].arrive)t2 += gWork[i].arrive;t2 = t2 + gWork[i].run;sum_turn = sum_turn + t2 - gWork[i].arrive;sum_dturn = sum_dturn + (t2 - gWork[i].arrive) / gWork[i].run;}else{if (t1 < gWork[i].arrive)t1 += gWork[i].arrive;t1 = t1 + gWork[i].run;sum_turn = sum_turn + t1 - gWork[i].arrive;sum_dturn = sum_dturn + (t1 - gWork[i].arrive) / gWork[i].run;}} }//先來先服務(wù)算法 void Fcfs() {unsigned n = static_cast<unsigned>(gWork.size());//按照來到的時(shí)間點(diǎn)排序,升序Work temp;for (unsigned i = 0; i < n; ++i){for (unsigned j = 0; j < n - i - 1; ++j){if (gWork[j].arrive > gWork[j + 1].arrive){temp = gWork[j + 1];gWork[j + 1] = gWork[j];gWork[j] = temp;}}}Dispatch();Output(); }//短作業(yè)優(yōu)先算法 void Sjf() {unsigned n = static_cast<unsigned>(gWork.size());//按照作業(yè)運(yùn)行時(shí)間的長短排序,升序Work temp;for (unsigned i = 0; i < n; ++i){for (unsigned j = 0; j < n - i - 1; ++j){if (gWork[j].run > gWork[j + 1].run){temp = gWork[j + 1];gWork[j + 1] = gWork[j];gWork[j] = temp;}}}Dispatch();Output(); }//高響應(yīng)比優(yōu)先算法 void Hrf() {int n = static_cast<int>(gWork.size());//按照來到的時(shí)間點(diǎn)排序,升序Work temp;for (int i = 0; i < n; ++i){for (int j = 0; j < n - i - 1; ++j){if (gWork[j].arrive > gWork[j + 1].arrive){temp = gWork[j + 1];gWork[j + 1] = gWork[j];gWork[j] = temp;}}}vector<Work> temp_work;for (int i = 0; i < n; ++i)temp_work.push_back(gWork[i]);gWork.clear();sum_turn = 0;//初始化sum_dturn = 0;double t1 = 0, t2 = 0;//同時(shí)運(yùn)行兩個(gè)作業(yè),設(shè)置兩個(gè)時(shí)間軸以記錄各個(gè)作業(yè)完成情況int i = 0, flag = 0;n = static_cast<int>(temp_work.size());double max_rate = 0, rate = 0;//運(yùn)行第一個(gè)作業(yè)for (i = 0; i < n; ++i){//rate = wait / run + 1rate = (temp_work[n - 1].arrive - temp_work[i].arrive) / temp_work[i].run + 1;if (max_rate < rate){max_rate = rate;flag = i;}}t1 = temp_work[flag].arrive + temp_work[flag].run;sum_turn = t1 - temp_work[flag].arrive;sum_dturn = (t1 - temp_work[flag].arrive) / temp_work[flag].run;gWork.push_back(temp_work[flag]);temp_work.erase(temp_work.begin() + flag);//已經(jīng)運(yùn)行的作業(yè)要?jiǎng)h去//運(yùn)行剩下的作業(yè)while (!temp_work.empty()){n = static_cast<int>(temp_work.size());flag = 0;max_rate = 0;rate = 0;if (t1 > t2)//表明t1有作業(yè)時(shí)t2空閑{//運(yùn)行第二個(gè)作業(yè)if (t2 == 0){for (i = 0; i < n; ++i){//rate = wait / run + 1rate = (temp_work[n - 1].arrive - temp_work[i].arrive) / temp_work[i].run + 1;if (max_rate < rate){max_rate = rate;flag = i;}}t2 = temp_work[flag].arrive + temp_work[flag].run;sum_turn = t2 - temp_work[flag].arrive;sum_dturn = (t2 - temp_work[flag].arrive) / temp_work[flag].run;gWork.push_back(temp_work[flag]);temp_work.erase(temp_work.begin() + flag);//已經(jīng)運(yùn)行的作業(yè)要?jiǎng)h去continue;}for (i = 0; i < n; ++i){if (temp_work[i].arrive <= t2){rate = (t2 - temp_work[i].arrive) / temp_work[i].run + 1;if (max_rate < rate){max_rate = rate;flag = i;}}elsebreak;}t2 += temp_work[flag].run;sum_turn = sum_turn + t2 - temp_work[flag].arrive;//turn = finish - arrivesum_dturn = sum_dturn + (t2 - temp_work[flag].arrive) / temp_work[flag].run;gWork.push_back(temp_work[flag]);temp_work.erase(temp_work.begin() + flag);//已經(jīng)運(yùn)行的作業(yè)要?jiǎng)h去}else{for (i = 0; i < n; ++i){if (temp_work[i].arrive <= t1){rate = (t1 - temp_work[i].arrive) / temp_work[i].run + 1;if (max_rate < rate){max_rate = rate;flag = i;}}elsebreak;}t1 += temp_work[flag].run;sum_turn = sum_turn + t1 - temp_work[flag].arrive;//turn = finish - arrivesum_dturn = sum_dturn + (t1 - temp_work[flag].arrive) / temp_work[flag].run;gWork.push_back(temp_work[flag]);temp_work.erase(temp_work.begin() + flag);//已經(jīng)運(yùn)行的作業(yè)要?jiǎng)h去}}Output(); }數(shù)據(jù):
A 0 7 B 2 10 C 5 20 D 7 30 E 12 40 F 15 8 G 4 8 H 6 20 I 8 10 J 10 125.2 實(shí)驗(yàn) 2:磁盤調(diào)度
5.2.1 實(shí)驗(yàn)?zāi)康?/h3>
5.2.2 實(shí)驗(yàn)內(nèi)容
| 訪問的磁道號(hào) | 50 | 100 | 180 | 20 | 90 | 150 | 70 | 80 | 101 | 60 | 120 | 40 | 110 | 30 |
| 請(qǐng)求服務(wù)到達(dá) | A | B | C | D | E | F | G | H | I | J | K | L | M | N |
5.2.3 源代碼
#include <iostream> #include <fstream> #include <vector> #include <cmath> #include <stdlib.h>using namespace std;struct Disk {char name;//請(qǐng)求服務(wù)到達(dá)序號(hào)int number;//訪問的磁道號(hào)Disk() {}Disk(char n, int num):name(n), number(num){}Disk operator =(const Disk& rhs){this->name = rhs.name;this->number = rhs.number;return *this;} };const int StartNum = 90;//開始磁道號(hào)為90vector<Disk> gDisk;//存儲(chǔ)請(qǐng)求服務(wù)到達(dá)的序列 vector<char> track;//磁道訪問順序 vector<int> MoveDistance;//移動(dòng)距離 //int FindOrder[MaxNumber];//尋號(hào)序列 double TotalDistance;//總共尋到長度 bool direction;//方向,true為向外,false為向內(nèi)void Readfile();//從txt文件中讀取請(qǐng)求服務(wù)信息 void Sortnum();//根據(jù)磁盤號(hào)進(jìn)行排序,升序 void Fcfs();//先來先服務(wù)算法 void Sstf();//最短尋道優(yōu)先算法 void Scan();//電梯調(diào)度算法,也是掃描算法 void Output();//輸出結(jié)果int main() {Readfile();Fcfs();Sstf();Scan();return 0; }void Readfile() {ifstream ifile;ifile.open("/home/jason/文檔/OS/Pro_2/data.txt");if(!ifile){cout << "文檔打開失敗!" << endl;exit(1);}char name;int num;while(ifile >> name >> num)gDisk.push_back(Disk(name, num));ifile.close(); } void Sortnum() {int i(0), j(0);int n = static_cast<int>(gDisk.size());Disk temp;for(i = 0; i < n; ++i){for(j = 0; j < n - i - 1; ++j){if(gDisk[j].number > gDisk[j + 1].number){temp = gDisk[j + 1];gDisk[j + 1] = gDisk[j];gDisk[j] = temp;}}} }//先來先服務(wù)算法 void Fcfs() {int tempNum = StartNum;//尋道當(dāng)前所在磁道號(hào)track.clear();MoveDistance.clear();int n = static_cast<int>(gDisk.size());//提出的申請(qǐng)數(shù)for(int i = 0; i < n; ++i){MoveDistance.push_back(abs(gDisk[i].number - tempNum));track.push_back(gDisk[i].name);tempNum = gDisk[i].number;}cout << "###############先來先服務(wù)算法:###############" << endl;Output(); } //最短尋道優(yōu)先算法 void Sstf() {int tempNum = StartNum;//尋道當(dāng)前所在磁道號(hào)track.clear();MoveDistance.clear();vector<Disk> temp_disk;int MinNum = 9999;//最短尋道數(shù)int flag = 0;//做標(biāo)記int n = static_cast<int>(gDisk.size());//提出的申請(qǐng)數(shù)for(int i = 0; i < n; ++i){temp_disk.push_back(gDisk[i]);}while(!temp_disk.empty()){MinNum = 9999;int num = 0;//臨時(shí)存儲(chǔ)尋道數(shù)flag = 0;n = static_cast<int>(temp_disk.size());for(int i = 0; i < n; ++i){num = abs(temp_disk[i].number - tempNum);if(MinNum > num){MinNum = num;flag = i;}}track.push_back(temp_disk[flag].name);//記錄第一個(gè)尋道號(hào)tempNum = temp_disk[flag].number;MoveDistance.push_back(MinNum);//記錄第一個(gè)尋道距離temp_disk.erase(temp_disk.begin() + flag);//已訪問的刪去}cout << "###############最短尋道優(yōu)先服務(wù)算法:###############" << endl;Output(); }//電梯調(diào)度算法 void Scan() {track.clear();MoveDistance.clear();//按磁道號(hào)進(jìn)行排序,升序Sortnum();int n = static_cast<int>(gDisk.size());vector<Disk> temp_disk;for(int i = 0; i < n; ++i)temp_disk.push_back(gDisk[i]);int tempNum = StartNum;int flag(0);for(int i = 0; i < n; ++i){if(temp_disk[i].number < tempNum)continue;else{flag = i;break;}}//最開始是向外尋道for(int i = flag; i < n; ++i){track.push_back(temp_disk[i].name);MoveDistance.push_back(temp_disk[i].number - tempNum);tempNum = temp_disk[i].number;}//然后向里尋道for(int i = flag - 1; i >= 0; --i){track.push_back(temp_disk[i].name);MoveDistance.push_back(tempNum - temp_disk[i].number);tempNum = temp_disk[i].number;}cout << "###############電梯調(diào)度算法:###############" << endl;Output();} //輸出結(jié)果 void Output() {int n = static_cast<int>(gDisk.size());//提出的申請(qǐng)數(shù)TotalDistance = 0;cout << "尋道序號(hào):" << " " << "尋道長度:"<<endl;for(int i = 0; i < n; ++i){cout << track[i] << " "<< MoveDistance[i] << endl;TotalDistance += MoveDistance[i];}cout << "平均尋道長度:" << (static_cast<double>(TotalDistance) / n) << endl;cout << endl; }數(shù)據(jù):
A 30 B 50 C 100 D 180 E 20 F 90 G 150 H 70 I 80 J 10 K 160 L 120 M 40 N 1105.3 實(shí)驗(yàn) 3:熟悉 linux 文件系統(tǒng)調(diào)用
5.3.1 實(shí)驗(yàn)?zāi)康?/h3>
5.3.2 實(shí)驗(yàn)內(nèi)容
使用文件系統(tǒng)調(diào)用編寫一個(gè)文件工具 filetools,使其具有以下功能:
1.創(chuàng)建新文件 2.寫文件 3.讀文件 4.修改文件權(quán)限 5.查看當(dāng)前文件權(quán)限 0.退出
提示用戶輸入功能號(hào),并根據(jù)用戶輸入的功能選擇相應(yīng)的功能。 文件按可變記錄文件組織,具體記錄內(nèi)容自行設(shè)計(jì)。
5.3.3 預(yù)備知識(shí)
用戶在針對(duì)文件進(jìn)行操作之前時(shí)一定要先打開它,這是由于系統(tǒng)需要根據(jù)用戶提供的參數(shù)來查找文件 的目錄項(xiàng),并由目錄項(xiàng)找到文件的磁盤 i 結(jié)點(diǎn),再將它調(diào)到內(nèi)存 i 結(jié)點(diǎn),才能建立用戶進(jìn)程與該文件之間的聯(lián)系。
同樣,在文件操作完畢后要關(guān)閉文件,以切斷用戶進(jìn)程與文件的聯(lián)系,釋放相關(guān)資源。
Open 系統(tǒng)調(diào)用
int open(const char *path, int flags); int open(const char *path, int flags,mode_t mode);一般情況下使用兩個(gè)參數(shù)的格式,只有當(dāng)打開的文件不存在時(shí)才使用 3 個(gè)參數(shù)的格式。參數(shù):
- Path 指向所要打開的文件的路徑名指針。
- Flag 標(biāo)志參數(shù),用來規(guī)定打開方式,必須包含以下 3 個(gè)之一:
- O_RDONLY 只讀方式
- O_WRONLY 只寫方式
- O_RDWR 讀寫方式
- 利用按位邏輯或“|”對(duì)下列標(biāo)志進(jìn)行任意組合:
- O_CREAT 如果文件不存在則創(chuàng)建該文件,若存在則忽略。
- O_TRUNC 如果文件存在則將文件長度截為 0,屬性和所有者不變。
- C_EXECL 如果文件存在且O_CREAT 被設(shè)置則強(qiáng)制 open 調(diào)用失敗。
- O_APPEND 每次寫入時(shí)都從文件尾部開始。
- Mode 是文件的訪問權(quán)限,分為文件所有者、文件用戶組和其他用戶。
Close 系統(tǒng)調(diào)用
對(duì)于一個(gè)進(jìn)程來說可以同時(shí)打開的文件是有限的,為了使文件標(biāo)識(shí)符能夠及時(shí)釋放,系統(tǒng)必須提供關(guān)閉文件操作。
Int close(int fd)- Fd 為打開文件時(shí)系統(tǒng)返回的文件標(biāo)識(shí)符。
- 系統(tǒng)執(zhí)行該系統(tǒng)調(diào)用時(shí),根據(jù) fd 值在該進(jìn)程的進(jìn)程打開文件表中找到 fd 標(biāo)識(shí),根據(jù)指針找到系統(tǒng)打開 文件表,再找到內(nèi)存i 結(jié)點(diǎn)表中相應(yīng)的 i 結(jié)點(diǎn),對(duì)其i_count 進(jìn)行減 1 操作, 然后釋放系統(tǒng)打開文件表中的表項(xiàng)和進(jìn)程打開文件表的表項(xiàng)。
- 結(jié)果:調(diào)用成功返回 0。
5.3.4 源代碼
#include <string.h> #include <unistd.h> #include <stdio.h> #include <fcntl.h>//flag標(biāo)志參數(shù) #include <sys/stat.h>//文件權(quán)限標(biāo)志位 #include <sys/types.h>#define MAX 10000 int fd;//打開文件時(shí)系統(tǒng)返回的文件標(biāo)識(shí)符 char *FileName;//要?jiǎng)?chuàng)建的文件名void Menu();//顯示主界面菜單 void CreateFile();//創(chuàng)建新文件 void WriteFile();//寫文件 void ReadFile();//讀文件 void ModifyPermission();//修改文件權(quán)限 void ShowPermission();//查看文件權(quán)限int main() {int select = 0;printf("########歡迎使用文件工具FileTools#######\n");while(1){Menu();scanf("%d", &select);switch (select) {case 0:close(fd);return 0;case 1:CreateFile();break;case 2:WriteFile();break;case 3:ReadFile();break;case 4:ModifyPermission();break;case 5:ShowPermission();break;default:printf("輸入有誤!請(qǐng)重新輸入:\n");}}return 0; }void Menu() {printf("########################################\n");printf("########1.創(chuàng)建新文件####################\n");printf("########2.寫文件########################\n");printf("########3.讀文件########################\n");printf("########4.修改文件權(quán)限##################\n");printf("########5.查看文件權(quán)限##################\n");printf("########0.安全退出######################\n");printf("請(qǐng)選擇:\n"); }//創(chuàng)建新文件 void CreateFile() {char name[32];printf("請(qǐng)輸入要?jiǎng)?chuàng)建的文件名:\n");scanf("%s", name);FileName = name;//O_RDWR:讀寫方式//O_TRUNC:如果文件存在則將文件長度截為0,屬性和所有者不變//O_CREAT:如果文件不存在則創(chuàng)建該文件,若存在則忽略fd = open(FileName, O_RDWR|O_TRUNC|O_CREAT, 0750);if(fd < 0)perror("Create");else{printf("文件創(chuàng)建成功!\n");printf("fd =%d\n", fd);//打印文件的fdclose(fd);//關(guān)閉文件} }//寫文件 void WriteFile() {char name[32];printf("請(qǐng)輸入要寫入信息的文件名:\n");scanf("%s", name);FileName = name;char buffer[MAX];//存取寫入的信息fd = open(FileName, O_WRONLY|O_APPEND);if(fd < 0){perror("Write");return;}printf("請(qǐng)輸入要寫入的信息:\n");int num = read(0,buffer, MAX);//讀取輸入信息,0表示標(biāo)從鍵盤標(biāo)準(zhǔn)輸入write(fd, buffer, num);//將讀入的信息寫入文件printf("文件寫入成功!\n");close(fd);//關(guān)閉文件 }//讀文件 void ReadFile() {char buffer[MAX];char name[32];printf("請(qǐng)輸入要讀取的文件名:\n");scanf("%s", name);FileName = name;fd = open(FileName,O_RDONLY);if(fd < 0){perror("Wrong");return;}int num = read(fd, buffer, MAX);printf("\n");write(1, buffer, num);//向顯示屏輸出,1表示標(biāo)準(zhǔn)輸出printf("\n文件讀取成功!\n");close(fd); }//修改文件權(quán)限 void ModifyPermission() {char name[32];printf("請(qǐng)輸入要修改權(quán)限的文件名:\n");scanf("%s", name);FileName = name;fd = open(FileName, O_RDONLY);if(fd < 0){perror("Modify");return;}printf("0.所有者用戶讀寫執(zhí)行\(zhòng)n");printf("1.所有者用戶只可讀\n");printf("2.所有者用戶只可寫\n");printf("3.所有者用戶只可執(zhí)行\(zhòng)n");printf("4.用戶組讀寫執(zhí)行\(zhòng)n");printf("5.用戶組只可讀\n");printf("6.用戶組只可寫\n");printf("7.用戶組只可執(zhí)行\(zhòng)n");printf("請(qǐng)選擇0-7:");int select;scanf("%d", &select);switch (select){case 0:chmod(FileName, S_IRWXU);break;//文件所有者讀寫執(zhí)行權(quán)限case 1:chmod(FileName, S_IRUSR);break;//文件所有者讀權(quán)限case 2:chmod(FileName, S_IWUSR);break;//文件所有者寫權(quán)限case 3:chmod(FileName, S_IXUSR);break;//文件所有者執(zhí)行權(quán)限case 4:chmod(FileName, S_IRWXG);break;//文件所屬組讀寫執(zhí)行權(quán)限case 5:chmod(FileName, S_IRGRP);break;//文件所屬組讀權(quán)限case 6:chmod(FileName, S_IWGRP);break;//文件所屬組寫權(quán)限case 7:chmod(FileName, S_IXGRP);break;//文件所屬執(zhí)行權(quán)限default:printf("錯(cuò)誤選擇!\n");}close(fd); }//查看文件權(quán)限 void ShowPermission() {//stat();獲取文件信息char name[32];printf("請(qǐng)輸入要修改權(quán)限的文件名:\n");scanf("%s", name);FileName = name;char *path = "/bin/ls";char *argv[4] = {"ls", "-l", FileName, NULL};execv(path, argv); }5.4 實(shí)驗(yàn) 4:進(jìn)程管理
5.4.1 實(shí)驗(yàn)?zāi)康?/h3>
5.4.2 實(shí)驗(yàn)內(nèi)容
-
父進(jìn)程使用系統(tǒng)調(diào)用 pipe() 建立一個(gè)管道,然后使用系統(tǒng)調(diào)用 fork() 創(chuàng)建兩個(gè)子進(jìn)程:子進(jìn)程1和子進(jìn)程2。
-
子進(jìn)程1每隔1秒通過管道向子進(jìn)程2發(fā)送數(shù)據(jù):I send message x times.(x 初值為1,以后發(fā)送一 次后做加一操作)子進(jìn)程 2 從管道讀出信息,并顯示在屏幕上。
-
父進(jìn)程用系統(tǒng)調(diào)用 signal() 來捕捉來自鍵盤的中斷信號(hào)(即按Ctrl+C 鍵);當(dāng)捕捉到中斷信號(hào)后,父進(jìn)程用系統(tǒng)調(diào)用 kill() 向兩個(gè)子進(jìn)程發(fā)出信號(hào),子進(jìn)程捕捉到信號(hào)后分別輸出如下信息后終止: Child Process 1 is killed by Parent! Child Process 2 is killed by Parent!。
-
父進(jìn)程等待兩個(gè)子進(jìn)程終止后,釋放管道并輸出如下的信息后終止 Parent Process is Killed!。
5.4.3 源代碼
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h>#include <sys/types.h> #include <sys/wait.h>pid_t child1, child2;//兩個(gè)子進(jìn)程 int fd[2]; void SignalHandler1(int iSignNo);//信號(hào)處理 void SignalHandler2(int iSignNo);int main() {int Count = 1;char buffer[40];char info[40];pid_t getpid();printf("Process Parent PID:%d\n", getpid());//創(chuàng)建無名管道,只能在父子或兄弟進(jìn)程間通信//fd[0]只能用于讀,fd[1]只能用于寫if(pipe(fd) < 0){printf("管道創(chuàng)建失敗!\n");return -1;}//設(shè)置軟中斷信號(hào)SIGINT,終端輸入Ctrl+C,進(jìn)程終止signal(SIGINT, SignalHandler1);//創(chuàng)建子進(jìn)程1,2child1 = fork();if(child1 == 0) //子進(jìn)程1{printf("Child Process 1 PID:%d\n", getpid());//設(shè)置忽略信號(hào),如果不設(shè)置,在子進(jìn)程運(yùn)行過程直接Ctrl+C,會(huì)造成進(jìn)程終止,//產(chǎn)生僵尸進(jìn)程,因此需要在子進(jìn)程中屏蔽,等子進(jìn)程被父進(jìn)程kill之后,再在//父進(jìn)程中Ctrl+C使進(jìn)程完全結(jié)束,就不會(huì)產(chǎn)生僵尸進(jìn)程了signal(SIGINT, SIG_IGN);//設(shè)置信號(hào)SIGUSR1signal(SIGUSR1, SignalHandler2);while(1){close(fd[0]);sprintf(info, "I send message %d times", Count);//管道長度受到限制,管道寫滿時(shí)寫入操作將被阻塞,直到管道中的數(shù)據(jù)被讀取write(fd[1], info, 30);//發(fā)送數(shù)據(jù)至管道數(shù)據(jù)++Count;//計(jì)數(shù)器+1sleep(1);//睡眠1s}}else if(child1 > 0)//返回父進(jìn)程{child2 = fork(); //父進(jìn)程創(chuàng)建子進(jìn)程2if(child2 == 0) //子進(jìn)程2{printf("Child Process 2 PID:%d\n", getpid());//設(shè)置忽略信號(hào)signal(SIGINT, SIG_IGN);//設(shè)置信號(hào)SIGUSR1signal(SIGUSR2, SignalHandler2);while(1){close(fd[1]);//當(dāng)數(shù)據(jù)被讀取后,數(shù)據(jù)將自動(dòng)被管道清除//接受管道數(shù)據(jù)read(fd[0], buffer, 40);//顯示管道數(shù)據(jù)printf("%s\n", buffer);}}else //返回父進(jìn)程{//等待子進(jìn)程1,2退出waitpid(child1, NULL, 0);//printf("Child Process 1 is over!\n");waitpid(child2, NULL, 0);//printf("Child Process 2 is over!\n");//關(guān)閉管道close(fd[0]);close(fd[1]);printf("Parent Process is Killed!\n");}}return 0; }void SignalHandler1(int iSignNo) {printf("\nParent recive signal Ctrl+C\n");if(iSignNo == SIGINT)//傳遞SIGUSR信號(hào)給子進(jìn)程{//SIGUSR1和SIGUSR2是用戶自定義信號(hào),進(jìn)程終止kill(child1, SIGUSR1);kill(child2, SIGUSR2);} }void SignalHandler2(int iSignNo) {close(fd[0]);close(fd[1]);if(child1 == 0 && iSignNo == SIGUSR1){printf("Child Process 1 is killed by Parent!\n");exit(0);}if(child2 == 0 && iSignNo == SIGUSR2){printf("Child Process 2 is killed by Parent!\n");exit(0);} }5.5 實(shí)驗(yàn) 5:請(qǐng)求分頁系統(tǒng)中的置換算法
5.5.1 實(shí)驗(yàn)?zāi)康?/h3>
5.5.2 實(shí)驗(yàn)內(nèi)容
1、通過如下方法產(chǎn)生一指令序列,共 320 條指令。
A. 在[0,319]的指令地址之間隨機(jī)選取一起點(diǎn) M;
B. 順序執(zhí)行一條指令,即執(zhí)行地址為 M+1 的指令;
C. 在前地址[0,M+1]中隨機(jī)選取一條指令并執(zhí)行,該指令的地址為 M1;
D. 順序執(zhí)行一條指令,其地址為 M1+1;
E. 在后地址[M1+2,319]中隨機(jī)選取一條指令并執(zhí)行,該指令的地址為 M2;
F. 順序執(zhí)行一條指令,其地址為 M2+1;
G. 重復(fù)A—F,直到執(zhí)行 320 次指令。
2、指令序列變換成頁地址流,設(shè) :
(1)頁面大小為1K;
(2) 用戶內(nèi)存容量為 4 頁到 32 頁,步長為 1;
(3)用戶虛存容量為 32K。在用戶虛存中,按每頁存放10 條指令排列虛存地址,即 320 條指令在虛存中的存放方式為: 第0條—第9條指令為第0頁(對(duì)應(yīng)虛存地址為[0,9]);第10條—第19條指令為第1頁(對(duì)應(yīng)虛存地址為[10,19]) ; …………………… 第310條—第319條指令為第31頁(對(duì)應(yīng)虛存地址為[310,319]) ;
按以上方式,用戶指令可組成 32 頁。
3、計(jì)算并輸出下述各種算法在不同內(nèi)存容量下的命中率。
A. 先進(jìn)先出(FIFO)頁面置換算法
B. 最近最久未使用(LRU)頁面置換算法–最近最少使用算法
C. 最佳(Optimal)頁面置換算法
5.5.3 源代碼
#include<iostream> #include<ctime> #include<cstdlib>using namespace std;int N = 3;//內(nèi)存 int Process[320];//頁面隊(duì)列 int Memory[32];//塊數(shù) int OPTQueue[320];//OPT算法的隊(duì)列 int FIFOQueue[320];//FIFO算法隊(duì)列 int LRUQueue[320];//LRU算法隊(duì)列 int ttime[320];//設(shè)置的一個(gè)時(shí)間標(biāo)志,FIFO算法時(shí)判斷哪個(gè)是最先進(jìn)來的 int flag[320];//設(shè)置一個(gè)標(biāo)志,LUR算法判斷哪個(gè)是最近最久未使用的 int ProcessNum;//頁面數(shù) int id[320];//320個(gè)進(jìn)程序列 int address[320];//zhilingzidian int Size = 0; int Randf(int l, int r) { return (rand() % (r - l + 1) + l); }void CreateProcess() {srand(static_cast<unsigned>(time(NULL)));Size = 0;for (int i = 0;i < 64;++i){int m = Randf(0, 319);id[Size++] = m + 1;m = Randf(0, m + 1);id[Size++] = m;id[Size++] = m + 1;m = Randf(m + 2, 319);id[Size++] = m;id[Size++] = m + 1;}cout << "指令序列:" << endl;for (int i = 0;i < Size;++i)cout << id[i] << " ";cout << endl; }//OPT算法找到最長未使用的 int longest(int start) {int i;int count[320];for (int i = 0;i < 320;++i)count[i] = 0;for (int j = 0;j < N;++j){for (i = start + 1;i < ProcessNum;i++){if (Memory[j] != OPTQueue[i])count[j]++;if (Memory[j] == OPTQueue[i])break;}}int ti = -1, mmax = -1;for (int i = 0;i < N;++i){if (mmax < Memory[i]){mmax = Memory[i];ti = i;}}return ti; } //OPT 算法 void OPT() {int i, j, k;int num = N;for (i = 0;i < ProcessNum;i++){OPTQueue[i] = Process[i];}for (i = 0;i < N;i++){Memory[i] = OPTQueue[i];}for (i = N;i < ProcessNum; ++i){for (j = 0;j < N;j++){if (Memory[j] == OPTQueue[i])break;}if (j == N){k = longest(i);Memory[k] = OPTQueue[i];num++;}}cout << "命中次數(shù):" << ProcessNum - num << endl;float str;str = (float)(ProcessNum - num) / ProcessNum;cout << "命中率=" << str * 100 << "%" << endl; } //FIFO算法找到最早進(jìn)來的那個(gè) int MaxTime() {int ti = -1, mmin = 100000;for (int i = 0;i<N;++i){if (mmin > ttime[i]){mmin = ttime[i];ti = i;}}return ti; } //FIFO算法 void FIFO() {int i, j, k;int num = N;for (i = 0;i<ProcessNum;i++){FIFOQueue[i] = Process[i];}for (i = 0;i<N;i++){Memory[i] = FIFOQueue[i];ttime[i] = i;}for (i = N;i<ProcessNum;i++){for (j = 0;j<N;j++){if (Memory[j] == FIFOQueue[i])break;}if (j == N){k = MaxTime();ttime[k] = i;Memory[k] = FIFOQueue[i];num++;}}cout << "命中次數(shù):" << ProcessNum - num << endl;float str;str = (float)(ProcessNum - num) / ProcessNum;cout << "命中率=" << str * 100 << "%" << endl; } //LRU算法找到最近最久未使用的 int MinFlag() {int ti = -1, mmin = 100000;for (int i = 0;i < N;++i){if (mmin > flag[i]){mmin = flag[i];ti = i;}}return ti; } //LRU算法 void LRU() {int i, j, k;int num = N;for (i = 0;i<ProcessNum;i++){LRUQueue[i] = Process[i];}for (i = 0;i<N;i++){Memory[i] = LRUQueue[i];flag[i] = i;}for (i = N;i<ProcessNum;i++){for (j = 0;j<N;j++){if (Memory[j] == LRUQueue[i]){flag[j] = i;break;}}if (j == N){k = MinFlag();flag[k] = i;Memory[k] = LRUQueue[i];num++;}}cout << "命中次數(shù):" << ProcessNum - num << endl;float str;str = (float)(ProcessNum - num) / ProcessNum;cout << "命中率=" << str * 100 << "%" << endl; } int main() {int i;while (N != 0) {cout << "-------------------頁面置換算法-------------------------" << endl;cout << "進(jìn)程數(shù):320" << endl;ProcessNum = 320;CreateProcess();//生成320個(gè)指令序列cout << "指令序列生成完畢" << endl << endl;for (i = 0;i < ProcessNum; ++i)Process[i] = id[i] / 10;N = 4;while (N != 1 && N != 0) {cout << "請(qǐng)輸入內(nèi)存容量:[4-32]\n1 for 重新生成指令序列\(zhòng)n0 for 退出程序" << endl;cin >> N;if (N == 0 || N == 1)break;cout << "OPT最佳置換算法" << endl;OPT();cout << endl;cout << "FIFO先進(jìn)先出頁面置換算法" << endl;FIFO();cout << endl;cout << "LRU最近最久未使用置換算法" << endl;LRU();cout << endl;}}return 0; }5.6 實(shí)驗(yàn) 6:進(jìn)程通信
5.6.1 實(shí)驗(yàn)?zāi)康?/h3>
5.6.2 實(shí)驗(yàn)內(nèi)容
編寫一主程序可以由用戶選擇如下三種進(jìn)程通信方式:
使用管道來實(shí)現(xiàn)父子進(jìn)程之間的進(jìn)程通信:子進(jìn)程向父進(jìn)程發(fā)送自己的進(jìn)程標(biāo)識(shí)符,以及字符串 is sending a message to parent。父進(jìn)程則通過管道讀出子進(jìn)程發(fā)來的消息,將消息顯示在屏幕上,然后終止。
使用消息緩沖隊(duì)列來實(shí)現(xiàn) client 進(jìn)程和 server 進(jìn)程之間的通信:server 進(jìn)程先建立一個(gè)關(guān)鍵字為 SVKEY(如75)的消息隊(duì)列,然后等待接收類型為REQ (例如 1)的消息;在收到請(qǐng)求消息后,它便顯示字符串 serving for client 和接收到的 client 進(jìn)程的進(jìn)程標(biāo)識(shí)數(shù),表示正在為 client 進(jìn)程服務(wù);然后再向 client 進(jìn)程發(fā)送應(yīng)答消息, 該消息的類型是 client 進(jìn)程的進(jìn)程標(biāo)識(shí)數(shù),而正文則是 server 進(jìn)程自己的標(biāo)識(shí) ID。client 進(jìn)程則向消息隊(duì)列發(fā)送類型為 REQ 的消息(消息的正文為自己的進(jìn)程標(biāo)識(shí) ID) 以取得 sever 進(jìn)程的服務(wù),并等待 server 進(jìn)程發(fā)來的應(yīng)答;然后顯示字符串 receive reply from 和接收到的 server 進(jìn)程的標(biāo)識(shí) ID。
使用共享存儲(chǔ)區(qū)來實(shí)現(xiàn)兩個(gè)進(jìn)程之間的進(jìn)程通信:進(jìn)程 A 創(chuàng)建一個(gè)長度為 512 字節(jié)的共享內(nèi)存,并顯示寫入該共享內(nèi)存的數(shù)據(jù);進(jìn)程 B 將共 享內(nèi)存附加到自己的地址空間,并向共享內(nèi)存中寫入數(shù)據(jù)。
5.6.3 源代碼
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <wait.h>#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/msg.h>struct msgform {long mtype;char mtext[250]; }msg;int msgqid, pid, *pint; void Menu(); void UsePipe();//使用管道實(shí)現(xiàn)父子進(jìn)程之間的進(jìn)程通信 void MessageDeque();//使用消息緩沖隊(duì)列實(shí)現(xiàn)C/S進(jìn)程之間的通信 void Client(); void Server(); void ShareMemory();//使用共享存儲(chǔ)區(qū)來實(shí)現(xiàn)兩個(gè)進(jìn)程之間的進(jìn)程通信 void A(); void B(); int main() {printf("######歡迎使用“進(jìn)程通信系統(tǒng)”######\n");while (1) {Menu();int select = 0;scanf("%d", &select);switch (select) {case 0:return 0;case 1:UsePipe();break;case 2:MessageDeque();break;case 3:ShareMemory();break;default:printf("您輸入的選擇無效,請(qǐng)重新輸入!\n");break;}}return 0; }void Menu() {printf("##################################\n");printf("1.管道實(shí)現(xiàn)父子進(jìn)程通信\n");printf("2.消息隊(duì)列C/S進(jìn)程通信\n");printf("3.共享存儲(chǔ)區(qū)的進(jìn)程通信\n");printf("0.安全退出\n");printf("請(qǐng)選擇通信方式:\n");}void UsePipe() {int fd[2];//fd[0]用于讀,fd[1]用于寫pid_t child;pid_t parent = getpid();printf("Process Parent PID:%d\n", parent);if(pipe(fd) < 0){printf("管道創(chuàng)建失敗!\n");return;}child = fork();if(child == 0)//進(jìn)入子進(jìn)程{char info[40];close(fd[0]);sprintf(info, "PID:%d is sending a message to parent", getpid());write(fd[1], info, 40);sleep(1);//休眠1sexit(0);}else //返回主進(jìn)程{close(fd[1]);char buffer[40];read(fd[0], buffer, 40);printf("%s\n", buffer);close(fd[0]);close(fd[1]);waitpid(child, NULL, 0);printf("Process child is over!\n");} }void MessageDeque() {int i = 0;while((i = fork()) == -1);//創(chuàng)建進(jìn)程1if(!i)Server();while((i = fork()) == -1);//創(chuàng)建進(jìn)程2if(!i)Client();wait(0);wait(0); } void Client() {msgqid = msgget(75, 0400);//打開75消息隊(duì)列pid = getpid();pint = (int *)msg.mtext;*pint = pid;msg.mtype = 1;//消息類型為1msgsnd(msgqid, &msg, sizeof(int), 0);//發(fā)送消息msgrcv(msgqid, &msg, 250, pid, 0);//接收消息printf("(client):reveice reply from pid=%d\n", *pint);exit(0); } void Server() {msgqid = msgget(75, 0400|IPC_CREAT);//創(chuàng)建75消息隊(duì)列msgrcv(msgqid, &msg, 250, 1, 0);//接收消息//把正文的內(nèi)容傳給pint,并強(qiáng)制轉(zhuǎn)換類型pint = (int *)msg.mtext;pid = *pint;//獲得client進(jìn)程標(biāo)識(shí)數(shù)printf("(server):serving for client pid=%d\n", pid);msg.mtype = pid;//消息類型為client*pint = getpid();msgsnd(msgqid, &msg, sizeof(int), 0);//發(fā)送消息exit(0); }void ShareMemory() {//需要包含頭文件<sys/types.h>,<sys/ipc.h>,<sys/shm.h>//shmget函數(shù)創(chuàng)建或打開一個(gè)新區(qū),返回一個(gè)共享存儲(chǔ)區(qū)ID//int shmget(key_t key, int size, int shmflg)//key:共享存儲(chǔ)區(qū)的名字,關(guān)鍵字,int型//size:共享存儲(chǔ)區(qū)的大小(以字節(jié)計(jì))//shmflg:用戶設(shè)置的標(biāo)志,如IPC_CREAT//IPC_CREAT 表示若系統(tǒng)中尚無指名的共享存儲(chǔ)區(qū),//則由核心建立一個(gè)共享存儲(chǔ)區(qū);如系統(tǒng)中已有共享存儲(chǔ)區(qū),便忽略IPC_CREAT//成功返回共享內(nèi)存的標(biāo)識(shí)符;不成功返回-1,errno 儲(chǔ)存錯(cuò)誤原因。pid_t a = 0;while ((a = fork()) == -1);if(!a)A();while ((a = fork()) == -1);if(!a)B();wait(0);wait(0); } void A() {int shmid = shmget(100, 512, 0777|IPC_CREAT);//創(chuàng)建共享存儲(chǔ)區(qū)char *addr = shmat(shmid, 0, 0);//獲取首地址printf("get:%s\n", addr);if(shmdt(addr) == 0)printf("A斷開鏈接成功!\n");exit(0); } void B() {int shmid = shmget(100, 512, 0777|IPC_CREAT);//打開共享存儲(chǔ)區(qū)char *message[] = {"B writes something!"};char *addr = shmat(shmid, 0, 0);//獲得共享存儲(chǔ)區(qū)首地址memset(addr, '\0', 512);//addr內(nèi)容初始化strncpy(addr, message[0], 512);//向內(nèi)存中寫信息if(shmdt(addr) == 0)printf("B斷開鏈接成功!\n");exit(0); }6. 課程設(shè)計(jì)報(bào)告及源代碼
https://download.csdn.net/download/diligent_lee/85015283
總結(jié)
以上是生活随笔為你收集整理的Linux 操作系统课程设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 算法导论答案(第一章)
- 下一篇: [转载]下载网页中的ts视频文件