操作系统实验报告
学院:电气与信息工程学院
学号:XXXXXXX
姓名:XXX
实验一
1.实验题目:进程调度
2.实验内容:通过该实验,使学生掌握在多道程序设计中,当若干个进程同时处于就绪状态,如何依据对应策略来决定那个进程优先占有处理机,加深对进程调度的理解。编写程序,能模拟优先级调度算法。
3.实验要求:输入:进程编号、进程优先级(或者进程编号、进程运行时间、时间片大小)
输出:进程调度序列。
4.实验过程:
#include<iostream>
#include<string>
#include<queue>
using namespace std;
typedef struct pcb {
string pName;
int priorityNumber;
float serviceTime;
float estimatedRunningtime;
char state;
bool operator<(const struct pcb &a)const {
return priorityNumber > a.priorityNumber || priorityNumber == a.priorityNumber&&estimatedRunningtime > a.estimatedRunningtime;
}
}PCB;
void createProcess(priority_queue<PCB> &p, int n) {
cout << endl << endl << "创建进程" << endl;
PCB r;
for (int i = 0; i<n; i++) {
cout << "请输入第" << i + 1 << "个进程的名字、优先数、服务时间(例如:A 12 8 ):";
cin >> r.pName;
cin >> r.priorityNumber;
cin >> r.serviceTime;
r.estimatedRunningtime = r.serviceTime;
r.state = 'R';
p.push(r);
}
cout << endl;
}
void printProcess(priority_queue<PCB> p) {
PCB s;
cout << "进程名\t优先数 服务时间 已运行时间 还剩运行时间" << endl;
while (p.size() != 0) {
s = p.top();
cout << s.pName << "\t" << s.priorityNumber << "\t " << s.serviceTime << "\t ";
cout << s.serviceTime - s.estimatedRunningtime << "\t " << s.estimatedRunningtime << endl;
p.pop();
}
cout << endl;
}
void runProcess(priority_queue<PCB> &p) {
PCB s;
while(p.size()!=0){
s = p.top();
p.pop();
cout << "正在运行的进程" << endl;
cout << "进程名\t优先数 服务时间 已运行时间 还剩运行时间" << endl;
cout << s.pName << "\t" << s.priorityNumber << "\t " << s.serviceTime << "\t ";
cout << s.serviceTime - s.estimatedRunningtime << "\t " << s.estimatedRunningtime << endl;
s.priorityNumber++;
s.estimatedRunningtime--;
if (s.estimatedRunningtime == 0) {
s.state = 'C';
}
else
p.push(s);
cout << "进程" << s.pName << "执行一次之后就绪队列中的进程" << endl;
printProcess(p);
}
cout << endl;
}
int main() {
priority_queue<PCB> p;
int n;
cout << "请输入进程的个数:";
cin >> n;
createProcess(p, n);
runProcess(p);
getchar();
getchar();
return 0;
}
5.实验结果:
实验二
1.实验题目: 银行家算法
2.实验内容: 通过该实验,使学生熟悉死锁产生的条件和原因,能够采用银行家算法有效地防止死锁的发生,加深对预防死锁,避免死锁,死锁检测和死锁解除等知识点的理解和掌握。
3.实验要求: 编写程序,能实现银行家算法,判断此时刻系统安全性:
输入:进程数、资源数、进程对资源的最大需求MAX,已分配矩阵allocation,资源总数
输出:给出安全与否的结论
4.实验过程:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 12,M = 12;
int n,m;
int mks[N][M];
int alcs[N][M];
int need[N][M];
int avlb[M];
int sod[N];
int bkup_alcs1[N][M],bkup_need1[N][M],bkup_avlb1[M];
int bkup_alcs2[N][M],bkup_need2[N][M],bkup_avlb2[M];
void myinput() {
cout << "请输入每个进程的Max Allocation Need" << endl;
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++) cin >> mks[i][j];
for(int j = 0; j < m; j++) cin >> alcs[i][j];
for(int j = 0; j < m; j++) cin >> need[i][j];
}
cout << "请输入Allocation" << endl;
for(int j = 0; j < m; j++) cin >> avlb[j];
}
void myoutput() {
cout << "\n资源分配表\n\n";
cout << "进程\\资源\tMax\t\tAllocation\tNeed" << endl;
for(int i = 0; i < n; i++) {
cout << "P" << i << "\t\t";
for(int j = 0; j < m; j++) cout << mks[i][j] << " ";
cout << "\t\t";
for(int j = 0; j < m; j++) cout << alcs[i][j] << " ";
cout << "\t\t";
for(int j = 0; j < m; j++) cout << need[i][j] << " ";
cout << endl;
}
cout << "Available" << endl;
for(int j = 0; j < m; j++) cout << avlb[j] << " ";
cout << endl;
}
void backup(int bkup_alcs[N][M],int bkup_need[N][M],int bkup_avlb[M]) {
memcpy(bkup_alcs,alcs,sizeof alcs);
memcpy(bkup_need,need,sizeof need);
memcpy(bkup_avlb,avlb,sizeof avlb);
}
void recovery(int bkup_alcs[N][M],int bkup_need[N][M],int bkup_avlb[M]) {
memcpy(alcs,bkup_alcs,sizeof alcs);
memcpy(need,bkup_need,sizeof need);
memcpy(avlb,bkup_avlb,sizeof avlb);
}
bool check_safe() {
backup(bkup_alcs1,bkup_need1,bkup_avlb1);
bool flag[N];
int cnt = 0;
memset(flag,0,sizeof flag);
while(1) {
int i;
for(i = 0; i < n; i++) {
if(flag[i]) continue;
int j;
for(j = 0; j < m; j++)
if(need[i][j] > avlb[j]) break;
if(j==m) break;
}
if(i==n) {
recovery(bkup_alcs1,bkup_need1,bkup_avlb1);
return false;
}
int id = i;
for(int j = 0; j < m; j++) avlb[j] += alcs[id][j];
flag[id] = true;
sod[cnt] = id;
cnt++;
if(cnt==n) {
recovery(bkup_alcs1,bkup_need1,bkup_avlb1);
return true;
}
}
}
int request_resource(int id,int req[M]) {
for(int j = 0; j < m; j++) if(req[j] > need[id][j]) return 1;
for(int j = 0; j < m; j++) if(req[j] > avlb[j]) return 2;
backup(bkup_alcs2,bkup_need2,bkup_avlb2);
for(int j = 0; j < m; j++) avlb[j] -= req[j];
for(int j = 0; j < m; j++) alcs[id][j] += req[j];
for(int j = 0; j < m; j++) need[id][j] -= req[j];
if(!check_safe()) {
recovery(bkup_alcs2,bkup_need2,bkup_avlb2);
return 3;
}
return 0;
}
int main() {
cout << "请输入进程数 资源数" << endl;
cin >> n >> m;
myinput();
myoutput();
if(check_safe()) {
cout << "是安全状态,安全序列为" << endl;
for(int i = 0; i < n; i++) {
cout << sod[i];
if(i!=n-1) cout << "->";
}
cout << endl;
}
else cout << "不是安全状态" << endl;
while(1) {
int id,req[M];
cout << "\n请输入要分配的进程 要分配的资源数量" << endl;
cin >> id;
if(id==9999)break;
for(int j = 0; j < m; j++) cin >> req[j];
int res = request_resource(id,req);
switch(res) {
case 0: cout << "分配成功" << endl; myoutput(); break;
case 1: cout << "分配失败!请求的资源数超过最大值!" << endl; break;
case 2: cout << "分配失败!系统中尚无足够的资源满足P" << id
<< "的申请!" << endl;break;
case 3: cout << "分配失败!假定分配后,无法通过安全性检查!"
<< endl;break;
}
}
return 0;
}
5.实验结果:
实验三
1.实验题目: 存储管理
2.实验内容: 通过该实验,使学生理解虚拟存储技术的特点,掌握合理分配空间的方法,掌握请求分页存储管理的多种页面置换算法。
3.实验要求: 编写程序,能LRU算法模拟页面置换过程:
输入,页面序列,分配的内存块数
输出:执行一个页面后内存中页面序列
4.实验过程:
#include<iostream>
using namespace std;
class memory{
public:
void init();
void alter(int a, int b);
int check_full();
int check_old();
int check_exist(int a);
void run();
void refresh();
friend int manage(memory *My_Memory, int ans, int a);
friend void show(memory *My_Memory, int ans);
private:
int page;
int time;
};
void memory::init(){
page = 0;
time = 0;
}
void memory::alter(int a, int b){
page = a;
time = b;
}
int memory::check_full()
{
if (page == 0 && time == 0){
return 1;
}
else{
return 0;
}
}
int memory::check_old(){
return time;
}
int memory::check_exist(int a){
if (page == a){
return 1;
}
else{
return 0;
}
}
void memory::run(){
if (page != 0){
time++;
}
}
void memory::refresh(){
time = 0;
}
int manage(memory *My_Memory, int ans, int a){
for (int i = 0; i < ans; i++){
if (My_Memory[i].check_exist(a)){
cout << "不发生中断,页面" << a << "已在内存块" << i << "中" << endl;
My_Memory[i].refresh();
return 1;
}
}
for (int i = 0; i < ans; i++){
if (My_Memory[i].check_full()){
cout << "发生中断," << "内存块" << i << "空闲中,页面" << a << "装入" << endl;
My_Memory[i].alter(a, 0);
return 0;
}
}
int max_time = 0;
int num = -1;
for (int i = 0; i < ans; i++){
if (My_Memory[i].check_old()>max_time){
max_time = My_Memory[i].check_old();
num = i;
}
}
cout << "发生中断," << "内存块" << num << "中页面" << My_Memory[num].page << "被替换,页面" << a << "装入" << endl;
My_Memory[num].alter(a, 0);
return 0;
}
void show(memory *My_Memory, int ans){
cout << "...................................." << endl;
cout << "内存块号";
for (int i = 0; i < ans; i++){
cout << " |" << i;
}
cout << "\n页面号 ";
for (int i = 0; i < ans; i++){
cout << " |" << My_Memory[i].page;
}
cout << "\n驻留时间";
for (int i = 0; i < ans; i++){
cout << " |" << My_Memory[i].time;
}
cout << "\n....................................\n" << endl;
}
int main(){
cout << "***************************" << endl;
cout << "*** 页面置换算法LRU ***" << endl;
cout << "*** 1.设置存储区块数 ***" << endl;
cout << "*** 2.页面调度模拟 ***" << endl;
cout << "*** 3.缺页率统计 ***" << endl;
cout << "*** 4.退出模拟器 ***" << endl;
cout << "***************************" << endl;
int ans, aans = 0, nohit = 0;
memory My_Memory[100];
int flag;
while (true){
cout << "\n请选择功能:";
cin >> flag;
if (flag == 1){
cout << "请输入存储区块数:";
cin >> ans;
for (int i = 0; i < ans; i++){
My_Memory[i].init();
}
nohit = 0;
aans = 0;
}
else if (flag == 2){
while (true){
for (int i = 0; i < ans; i++){
My_Memory[i].run();
}
cout << "请输入要调入的页面(输入0结束):";
int a;
cin >> a;
if (a == 0){
break;
}
aans++;
if (!manage(My_Memory, ans, a)){
nohit++;
}
show(My_Memory, ans);
}
}
else if (flag == 3){
cout << "*****************" << endl;
cout << "调度作业 " << aans << "次\n中断 " << nohit << "次\n缺页率 " << double(nohit) / aans * 100.00 << "%" << endl;
cout << "*****************" << endl;
}
else if (flag == 4){
cout << "成功退出!\n" << endl;
break;
}
}
return 0;
}
5.实验结果:
实验四
1.实验题目: 磁盘调度
2.实验内容: 通过该实验,使学生掌握当若干个要求访问磁盘的输入输出要求同时出现时,系统应该如何按照最佳次序执行访问磁盘的请求,理解和掌握磁盘调度的动态运行原理和机制。
3.实验要求: 编写程序,能模拟SSTF磁盘调度算法:
输入:进程访问的磁道序列,及当前磁头所在磁道号
输出:磁道访问序列
4.实验过程:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<math.h>
#define maxsize 1000
using namespace std;
int decide(char str[])
{
int i=0;
while(str[i]!='\0')
{
if(str[i]<'0'||str[i]>'9')
{
return 0;
break;
}
i++;
}
return i;
}
int trans(char str[],int a)
{
int i;
int sum=0;
for(i=0;i<a;i++)
{
sum=sum+(int)((str[i]-'0')*pow(10,a-i-1));
}
return sum;
}
int *bubble(int cidao[],int m)
{
int i,j;
int temp;
for(i=0;i<m;i++)
for(j=i+1;j<m;j++)
{
if(cidao[i]>cidao[j])
{
temp=cidao[i];
cidao[i]=cidao[j];
cidao[j]=temp;
}
}
cout<<"排序后的磁盘序列为:";
for( i=0;i<m;i++)
{
cout<<cidao[i]<<" ";
}
cout<<endl;
return cidao;
}
void FCFS(int cidao[],int m)
{
int now;
int sum=0;
int j,i;
int a;
char str[100];
float ave;
cout<<"磁盘请求序列为:";
for( i=0;i<m;i++)
{
cout<<cidao[i]<<" ";
}
cout<<endl;
cout<<"请输入当前的磁道号:";
B: cin>>str;
a=decide(str);
if(a==0)
{
cout<<"输入数据的类型错误,请重新输入!"<<endl;
goto B;
}
else
now=trans(str,a);
sum+=abs(cidao[0]-now);
cout<<"磁盘扫描序列为:";
for( i=0;i<m;i++)
{
cout<<cidao[i]<<" ";
}
for(i=0,j=1;j<m;i++,j++)
{
sum+=abs(cidao[j]-cidao[i]);
ave=(float)(sum)/(float)(m);
}
cout<<endl;
cout<<"平均寻道长度:"<<ave<<endl;
}
void SSTF(int cidao[],int m)
{
int k=1;
int now,l,r;
int i,j,sum=0;
int a;
char str[100];
float ave;
cidao=bubble(cidao,m);
cout<<"请输入当前的磁道号:";
C: cin>>str;
a=decide(str);
if(a==0)
{
cout<<"输入数据的类型错误,请重新输入!"<<endl;
goto C;
}
else
now=trans(str,a);
if(cidao[m-1]<=now)
{
cout<<"磁盘扫描序列为:";
for(i=m-1;i>=0;i--)
cout<<cidao[i]<<" ";
sum=now-cidao[0];
}
if(cidao[0]>=now)
{
cout<<"磁盘扫描序列为:";
for(i=0;i<m;i++)
cout<<cidao[i]<<" ";
sum=cidao[m-1]-now;
}
if(now>cidao[0]&&now<cidao[m-1])
{
cout<<"磁盘扫描序列为:";
while(cidao[k]<now)
{
k++;
}
l=k-1;
r=k;
while((l>=0)&&(r<m))
{
if((now-cidao[l])<=(cidao[r]-now))
{
cout<<cidao[l]<<" ";
sum+=now-cidao[l];
now=cidao[l];
l=l-1;
}
else
{
cout<<cidao[r]<<" ";
sum+=cidao[r]-now;
now=cidao[r];
r=r+1;
}
}
if(l==-1)
{
for(j=r;j<m;j++)
{
cout<<cidao[j]<<" ";
}
sum+=cidao[m-1]-cidao[0];
}
else
{
for(j=l;j>=0;j--)
{
cout<<cidao[j]<<" ";
}
sum+=cidao[m-1]-cidao[0];
}
}
ave=(float)(sum)/(float)(m);
cout<<endl;
cout<<"平均寻道长度: "<<ave<<endl;
}
void SCAN(int cidao[],int m)
{
int k=1;
int now,l,r,d;
int i,j,sum=0;
int a;
char str[100];
float ave;
cidao=bubble(cidao,m);
cout<<"请输入当前的磁道号:";
D: cin>>str;
a=decide(str);
if(a==0)
{
cout<<"输入数据的类型错误,请重新输入!"<<endl;
goto D;
}
else
now=trans(str,a);
if(cidao[m-1]<=now)
{
cout<<"磁盘扫描序列为:";
for(i=m-1;i>=0;i--)
cout<<cidao[i]<<" ";
sum=now-cidao[0];
}
if(cidao[0]>=now)
{
cout<<"磁盘扫描序列为:";
for(i=0;i<m;i++)
cout<<cidao[i]<<" ";
sum=cidao[m-1]-now;
}
if(now>cidao[0]&&now<cidao[m-1])
{
while(cidao[k]<now)
{
k++;
}
l=k-1;
r=k;
cout<<"请输入当前移动臂的移动的方向 (1 表示向外 ,0表示向内) : ";
cin>>d;
if(d==0)
{
cout<<"磁盘扫描序列为:";
for(j=l;j>=0;j--)
{
cout<<cidao[j]<<" ";
}
for(j=r;j<m;j++)
{
cout<<cidao[j]<<" ";
}
sum=now-2*cidao[0]+cidao[m-1];
}
else
{
cout<<"磁盘扫描序列为:";
for(j=r;j<m;j++)
{
cout<<cidao[j]<<" ";
}
for(j=l;j>=0;j--)
{
cout<<cidao[j]<<" ";
}
sum=-now-cidao[0]+2*cidao[m-1];
}
}
ave=(float)(sum)/(float)(m);
cout<<endl;
cout<<"平均寻道长度: "<<ave<<endl;
}
void CSCAN(int cidao[],int m)
{
int k=1;
int now,l,r;
int i,j,sum=0;
int a;
char str[100];
float ave;
cidao=bubble(cidao,m);
cout<<"请输入当前的磁道号:";
E: cin>>str;
a=decide(str);
if(a==0)
{
cout<<"输入数据的类型错误,请重新输入!"<<endl;
goto E;
}
else
now=trans(str,a);
if(cidao[m-1]<=now)
{
cout<<"磁盘扫描序列为:";
for(i=0;i<m;i++)
cout<<cidao[i]<<" ";
sum=now-2*cidao[0]+cidao[m-1];
}
if(cidao[0]>=now)
{
cout<<"磁盘扫描序列为:";
for(i=0;i<m;i++)
cout<<cidao[i]<<" ";
sum=cidao[m-1]-now;
}
if(now>cidao[0]&&now<cidao[m-1])
{
cout<<"磁盘扫描序列为:";
while(cidao[k]<now)
{
k++;
}
l=k-1;
r=k;
for(j=r;j<m;j++)
{
cout<<cidao[j]<<" ";
}
for(j=0;j<r;j++)
{
cout<<cidao[j]<<" ";
}
sum=2*cidao[m-1]+cidao[l]-now-2*cidao[0];
}
ave=(float)(sum)/(float)(m);
cout<<endl;
cout<<"平均寻道长度: "<<ave<<endl;
}
int main()
{
int a;
int c;
int cidao[maxsize];
int i=0,count;
char str[100];
cout<<"请输入磁道序列(0结束):"<<endl;
A:cin>>str;
a=decide(str);
if(a==0)
{
cout<<"输入数据的类型错误,请重新输入!"<<endl;
goto A;
}
else
cidao[i]=trans(str,a);
i++;
while(cidao[i-1]!=0)
{
cin>>str;
a=decide(str);
if(a==0)
cout<<"输入数据的类型错误,请重新输入!"<<endl;
else
{
cidao[i]=trans(str,a);
i++;
}
}
count=i-1;
cout<<"你输入的磁道序列为:";
for(i=0;i<count;i++)
{
cout<<cidao[i]<<" ";
}
cout<<endl;
while(1)
{
cout<<endl;
cout<<"**********************************************"<<endl; cout<<"****** 系统菜单 ******"<<endl;
cout<<"**********************************************"<<endl;
cout<<"*** ***"<<endl;
cout<<"** 1. 先来先服务 **"<<endl;
cout<<"** **"<<endl;
cout<<"** 2. 最短寻道时间优先 **"<<endl;
cout<<"** **"<<endl;
cout<<"** 3. 扫描调度 **"<<endl;
cout<<"** **"<<endl;
cout<<"** 4. 循环扫描 **"<<endl;
cout<<"** **"<<endl;
cout<<"** 5. 退出 **"<<endl;
cout<<"*** ***"<<endl; cout<<"**********************************************"<<endl; cout<<"**********************************************"<<endl;
G:cout<<"请选择算法:";
F:cin>>str;
a=decide(str);
if(a==0)
{
cout<<"输入数据的类型错误,请重新输入!"<<endl;
goto F;
}
else
c=trans(str,a);
if(c==5)
break;
if(c>5)
{
cout<<"数据输入错误!请重新输入"<<endl;
goto G;
}
switch(c)
{
case 1:
FCFS(cidao,count);
break;
case 2:
SSTF(cidao,count);
break;
case 3:
SCAN(cidao,count);
break;
case 4:
CSCAN(cidao,count);
break;
}
}
return 0;
}
5.实验结果:
实验感想
通过本次实验,我深刻的理解了操作系统中线程资源的分配方式和进程的调度方式。操作系统实验重在理解每一个算法的意图和目的,那么就选择适当的数据结构模拟过程就可以完成相关算法了。通过此次实验,我进一步理解了三种页面置换算法。最佳置换算法是一种理想化的算法,它具有最好的性能,但实际上却很难与实现。先进先出的算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰,该算法实现简单。最近最久未使用(LRU) 的页面置换算法,是根据页面调入内存后的使用情况进行决策的,LRU置换算法虽然是一种比较好的算法,但要求系统有较多的支持硬件,如:寄存器或栈。