操作系统实验

实验一 处理器管理-优先数调度算法

用户自定义个结构体名字叫做 P C B PCB PCB,因为我们需要按照优先数调度,所以我的做法就是把这个静态的等待队列按照优先数递增排序即可,因为使用了 C + + C++ C++ a l g o r i t h m algorithm algorithm库里面的 s o r t sort sort快速排序函数它自定义使用 l e s s less less也就是小于号比较规则,所以我们需要重载这个 P C B PCB PCB类中的小于号比较。接下来输出即可。

#include 
#include  // sort()快排函数
#include 
using namespace std;
#define endl '\n'
struct PCB {
	string name;	//进程名字
	double st_time;	//进入就绪队列的时间
	int id;	//优先级
	double tim;	//估计运行时间
	bool flag;	//进程状态
	bool operator < (const PCB A) const {
		return this->id < A.id;
	}
};

vector<PCB> a;

void print() {
	cout << "当前就绪队列的等待进程个数" << a.size() << endl;
	cout << "输出模式是:进程名字(优先级,运行时间)" << endl;
	for (int i = 0; i < a.size(); ++i) {
		cout << a[i].name << "(" << a[i].id << "," << a[i].tim << ")" << "<--";
	}
	cout << endl;
}

int main() {
	int n;
	cout << "请输入当前进程的数量n: ";
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		PCB tmp;
		cout << "请输入第" << i << "号进程的名字 ";
		cin >> tmp.name;
		cout << "请输入第" << i << "号进程的优先级 ";
		cin >> tmp.id;
		cout << "请输入第" << i << "号进程的运行时间(秒) ";
		cin >> tmp.tim;
		tmp.flag = false;
		a.push_back(tmp);
	}
	sort(a.begin(), a.end());
	double sum_time = 0.0;	//运行总时间
	while (a.size()) {
		print();	//打印当前就绪队列情况
		PCB now = a.front();
		a.erase(a.begin());
		cout << "当前名字:" << now.name << endl;
		cout << "优先级:" << now.id << endl;
		cout << "运行时间:" << now.tim << endl;
		sum_time += now.tim;
		cout << "当前进程执行完毕是总花费时间是:" << sum_time << endl;
	}
	cout << "<---- 就绪队列为空,调度进程结束" << endl;
	return 0;
}

实验二 处理器管理-银行家算法

主要是理解到什么是银行家算法的预分配,首先我们第一次输入只需要输入的变量只有

  1. 系统拥有的最大资源数
  2. 当前进行的并发进程数目
  3. 每个进程的起始资源占有量以及完成任务需要的资源数

在输入完上方的起始条件之后,需要你做一次安全检测,判断当前是否处于安全状态。如果起始就不处于安全状态那么也没必要往后面请求了,再怎么请求也不会变得安全状态。

那么在安全状态情况下,一条条的输入什么进程请求了多少资源,首先需要判断,是不是这个进程有的资源数加上当前申请的资源数有没有超过所需的最大资源数,如果超过了那么直接中断返回。否则就进行预分配。我们假设把这个进程拥有的资源数加上它申请的资源数,看看是不是存在一个合法的安全序列,如果找不到那就要撤销预分配也就是把之前累加到拥有的资源数里面的申请的资源数减掉去,如果存在一个合法的序列,在查询的时候就可以进行记录了。

那么有关安全检测算法的实现,使用一个临时变量 s u m sum sum等于系统拥有的资源数,首先遍历一遍全部的进程,如果进程当前拥有的资源数不等于它完成这个任务需要的,那么把它的状态也就是我下面结构体中的 v i s vis vis置为0,并且还需要把 s u m sum sum减掉它现在占有的资源数。如果当前占有的资源数等于的完成这个任务需要的资源数,直接在答案容器中插入进程名称。

接下来写一个死循环去判断全部的进程,如果进程的 v i s vis vis还是0的话,判断是否可以用当前尚存的资源满足它剩下需要的资源数。并且死循环直到一次修改都没有,可以使用一个标记去辨别。最终判断是不是全部的进程的 v i s vis vis都被置为了1,如果存在一个0,说明存在一个进程无法结束,说明没找到安全序列,返回即可 f a l s e false false

#include
#include
#include
#include
using namespace std;

const int N = 100 + 7;
struct PCB {
	string name; // 进程名称
	int now; // 已经占有的资源数
	int sum; // 需求的总数
	bool vis; // 能否执行完的标志,1代表可以
}a[N]; // a是初始,对b操作方便回溯

int n; // 进程数量
int sys_sum; // 系统拥有的资源
vector<string> ans; // 存储不发生死锁的进程推进顺序
unordered_map<string, int> mp; // 开C++11标准

bool check() {
	ans.clear();
	int sum = sys_sum;
	for (int i = 0; i < n; ++i) {
		if (a[i].now != a[i].sum)
			a[i].vis = 0, sum -= a[i].now;
		else
			ans.push_back(a[i].name); // 在这个容器中的结尾插入一个东西
	}
	bool flag = 0;
	while (true) {
		flag = 0;
		for (int i = 0; i < n; ++i) {
			if (a[i].vis)	continue;
			else if (a[i].sum - a[i].now <= sum) {
				flag = 1;
				a[i].vis = 1;
				sum += a[i].now;
				ans.push_back(a[i].name);
			}
		}
		if (flag == 0)
			break;
	}
	flag = 1; // 假定可以完全分配
	for (int i = 0; i < n; ++i)
		if (a[i].vis == 0)
			flag = 0; // 存在一个进程无法结束,代表当前状态不安全
	return flag;
}

void check_sys() {
	if (check()) {
		puts("当前处于安全状态");
		puts("找到的一组不发生死锁的进程推进序列是");
		for (auto& it : ans)
			cout << it << ", ";
		cout << endl;
	}
	else {
		puts("初始序列就不处于安全状态,中断返回");
		return;
	}
	while (true) {
		string name;
		int now;
		puts("输入当前请求资源的进程名字以及资源数");
		cin >> name >> now;
		int id = mp[name];
		if (a[id].now + now > a[id].sum) {
			cout << name << "请求资源数+已经占有的资源数大于该进程需要的总和,中断返回" << endl;
			continue;
		}
		a[id].now += now; // 预分配
		if (check()) { // 安全检测
			puts("当前处于安全状态");
			puts("找到的一组不发生死锁的进程推进序列是");
			for (auto& it : ans)
				cout << it << ", ";
			cout << endl;
		}
		else {
			puts("当前处于不安全状态,撤销预分配分配给该进程申请的资源数");
			a[id].now -= now; // 撤销预分配
		}
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cout << "输入系统共有几个资源" << endl;
	cin >> sys_sum;
	cout << "输入共有几个并发进程" << endl;
	cin >> n;
	cout << "输入进程名字,已占有资源数,最大需求" << endl;
	for (int i = 0; i < n; ++i) {
		string name;
		int now, sum;
		cin >> name >> now >> sum;
		mp[name] = i;
		a[i] = { name, now, sum, 0 }; // vis初值都为false
	}
	check_sys();
	return 0;
}

实验三 作业调度-响应比高优先调度算法

记录截止时间,判断那些作业进入了等待态,从这些作业中选择相应比最高的进入CPU。

#include 
using namespace std;
#define all(__vv__) (__vv__).begin(), (__vv__).end()
typedef long long ll;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())	s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)	putchar(op); return; }	char F[40]; ll tmp = x > 0 ? x : -x;	if (x < 0)putchar('-');	int cnt = 0;	while (tmp > 0) { F[cnt++] = tmp % 10 + '0';		tmp /= 10; }	while (cnt > 0)putchar(F[--cnt]);	if (op)	putchar(op); }

struct Work {
	string name = "";
	int enter_time = 0; // 进入时间
	int run_time = 0; // 运行时间
	bool flag = false; // true为作业的完成
	bool operator < (const Work A) const {
		return enter_time < A.enter_time;
	}
};
vector<Work> p;

int main() {
	printf("作业总数n=");
	int n = read();
	puts("每个作业的作业名, 进入时间, 运行时间");
	for (int i = 1; i <= n; ++i) {
		string name;
		int h, m;
		int run_time;
		cin >> name;
		scanf("%d:%d %d", &h, &m, &run_time);
		p.push_back({ name, h * 60 + m, run_time, false });
	}
	sort(all(p));
	int st = p[0].enter_time;
	double ans = 0.0;
	for (int i = 1; i <= n; ++i) {
		priority_queue<pair<double, int>> tmp;
		for (int j = 0; j < n; ++j) {
			if (p[j].flag)	continue;
			if (p[j].enter_time <= st) // 可加入下一次的计算相应比的作业
				tmp.push({ 1.0 * (st - p[j].enter_time + p[j].run_time) / p[j].run_time,j });
		}
		double check = tmp.top().first;
		int idx = tmp.top().second;
		cout << "当前选择的作业是" << p[idx].name << "相应比为:" << check << endl;
		st = st + p[idx].run_time;
		ans += st - p[idx].enter_time;
		cout << "周转时间为:" << st - p[idx].enter_time << endl;
		p[idx].flag = true;
	}
	cout << "平均周转时间为:" << ans / n << endl;
	return 0;
}
/*
A 8:00 120
B 9:00 10
C 8:50 50
D 9:50 20
*/

实验四 存储管理-可变分区存储管理的空间分配与去配

#include
#include
#include
#include
#include
using namespace std;

const int N = 1e5 + 7;
struct Node {
	int id; // 分区编号
	int st;
	int len;
	string name;
}p[N], s[N], out[N]; // p是已分配表,s是可分配表
int lenp, lens;
int m;

const bool cmp1(const Node& A, const Node& B) {
	return A.st < B.st;
}
const bool cmp2(const Node& A, const Node& B) {
	return A.len < B.len;
}
const bool cmp3(const Node& A, const Node& B) {
	return A.len > B.len;
}

int find(string& name) {
	for (int i = 0; i < lenp; ++i) {
		if (p[i].name == name)	return i;
	}
	return -1;
}

void print() {
	sort(p, p + lenp, cmp1);
	sort(s, s + lens, cmp1);
	puts("-------已分配状态表-------");
	puts("序号\t始址\t长度\t作业名");
	for (int i = 0; i < lenp; ++i) {
		printf("%d\t%d\t%d\t", p[i].id, p[i].st, p[i].len);
		cout << p[i].name << endl;
	}
	printf("------------------------------------\n\n");
	puts("-------可分配状态表-------");
	puts("序号\t始址\t长度\t作业名");
	for (int i = 0; i < lens; ++i) {
		printf("%d\t%d\t%d\t", s[i].id, s[i].st, s[i].len);
		cout << s[i].name << endl;
	}
	printf("------------------------------------\n\n");
}

void del_p(int idx) {
	for (int i = idx + 1; i < lenp; ++i)
		p[i - 1] = p[i];
	--lenp;
}

void del_s(int idx) {
	for (int i = idx + 1; i < lens; ++i)
		s[i - 1] = s[i];
	--lens;
}

int main() {
	puts("输入用户可用的主存大小");
	scanf("%d", &m);
	s[lens++] = { 0,0,m }; // 初始状态全部用户区都是空闲的
	int op1, op2;
	string name;
	int sz;
	print();
	puts("输入操作 op, 0代表某个作业完成,1代表某个作业调入主存");
	while (~scanf("%d", &op1)) {
		if (op1) {
			puts("输入选择的分配算法:\n1、最先适应算法\n2、最优适应算法\n3、最坏适应算法\n");
			scanf("%d", &op2);
			puts("输入调入主存的作业名字以及所需空间");
			cin >> name >> sz;
			if (op2 == 1)
				sort(s, s + lens, cmp1);
			else if (op2 == 2)
				sort(s, s + lens, cmp2);
			else if (op2 == 3)
				sort(s, s + lens, cmp3);
			int pos = -1;
			for (int i = 0; i < lens; ++i) {
				if (s[i].len >= sz) {
					pos = i;
					break;
				}
			}
			if (pos == -1) {
				puts("无空闲区分配");
			}
			else if (s[pos].len == sz) {
				p[lenp] = { lenp,s[pos].st,s[pos].len,name };
				++lenp;
				del_s(pos);
			}
			else {
				p[lenp] = { lenp,s[pos].st,sz,name };
				++lenp;
				s[pos].st += sz;
				s[pos].len -= sz;
			}
		}
		else {
			puts("输入需要释放的主存空间的作业名字");
			cin >> name;
			int pos = find(name);
			if (pos == -1) {
				puts("改作业不在主存中,中断返回");
				continue;
			}
			int st = p[pos].st, len = p[pos].len;
			int flag1 = -1, flag2 = -1;
			for (int i = 0; i < lens; ++i) {
				if (s[i].st == st + len) { // 下方有空闲区
					flag1 = i;
					break;
				}
			}
			for (int i = 0; i < lens; ++i) {
				if (s[i].st + s[i].len == st) { // 上方有空闲区
					flag2 = i;
					break;
				}
			}
			if (flag1 != -1 and flag2 != -1) {
				s[flag2].len += len + s[flag1].len;
				del_s(flag1);
			}
			else if (flag1 != -1) {
				s[flag1].st = st;
				s[flag1].len += len;
			}
			else if (flag2 != -1) {
				s[flag2].len += len;
			}
			else {
				s[lens] = { lens,st,len,"" };
				++lens;
			}
			del_p(pos);
		}
		print();
		puts("输入操作 op, 0代表某个作业完成,1代表某个作业调入主存");
	}
	return 0;
}

实验五 存储管理-请求分页式存储管理的页面置换

#include
#include
#include
using namespace std;

bool find_x(vector<int>& p, int x) { // 在p里面判断是否存在x
	for (auto& it : p)
		if (it == x)	return true;
	return false;
}

void print(vector<int>& p) { // 按照空格分隔数组中的元素并且最后换行输出
	int n = p.size();
	for (int i = 0; i < n; ++i)
		printf("%d%c", p[i], " \n"[i + 1 == n]);
}

int main() {
	int n, m, cnt = 0;
	cout << "输入分配给一个作业的物理块数(m)以及作业总数(n),使用空格分离" << endl;
	cin >> m >> n;
	vector<int> out, now;
	cout << "输入n个页面编号,使用空格分离" << endl;
	for (int i = 0; i < n; ++i) {
		int x;
		cin >> x;
		if (!find_x(now, x)) {
			++cnt; // 如果当前主存不存在x,说明产生一次缺页中断
			out.push_back(x);
			now.push_back(x);
		}
		if (now.size() > m)	now.erase(now.begin());
		// 如果超过了分配给作业的物理块数,那么就让最先进来的主存的页出去

		cout << "处理到第" << i + 1 << "个作业时,在主存中的作业编号为" << endl;
		print(now);
	}
	cout << "缺页中断时所淘汰的页面号为" << endl;
	print(out);
	printf("缺页中断率为:%.2f%%\n", 100.0 * cnt / n);
	return 0;
}

实验六 设备管理-电梯调度算法

除了排序,就是纯粹的模拟了,注意一些边界问题,数组越界就会产生错误的结果。

#include 
using namespace std;
#define all(__vv__) (__vv__).begin(), (__vv__).end()
typedef long long ll;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())	s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)	putchar(op); return; }	char F[40]; ll tmp = x > 0 ? x : -x;	if (x < 0)putchar('-');	int cnt = 0;	while (tmp > 0) { F[cnt++] = tmp % 10 + '0';		tmp /= 10; }	while (cnt > 0)putchar(F[--cnt]);	if (op)	putchar(op); }

int main() {
	printf("输入总的柱面数 L=");
	int l = read();
	printf("输入刚访问完的柱面m=");
	int m = read();
	printf("输入柱面的访问方向1代表磁头从外往内移动,-1代表磁头由内往外移动\n");
	printf("op=");
	int op = read();
	printf("输入系统需要访问的柱面数量n=");
	int n = read();
	puts("输入以空格分隔的柱面号p[i]");
	vector<int> p; // 动态扩容数组,存储待访问的柱面号
	for (int i = 1; i <= n; ++i) {
		int x = read();
		p.push_back(x);
	}
	sort(all(p));
	int ans = 0;
	if (op == 1) { // 最外层的柱面为0柱面
		int st = upper_bound(all(p), m) - p.begin(); // 找到第一个大于m的下标
		print(m, ',');
		if (st != n) { // m 右边存在需要访问的柱面号
			ans += p[st] - m;
			print(p[st], ',');
			for (int i = st; i < n - 1; ++i)
				ans += p[i + 1] - p[i],
				print(p[i + 1], ',');
			if (st != 0)
				ans += p[n - 1] - p[st - 1], // 移动到第一个小于m的下标处,注意可能不存在
				print(p[st - 1], ',');
			for (int i = st - 1; i > 0; --i)
				ans += p[i] - p[i - 1],
				print(p[i - 1], ',');
		}
		else { // 直接向外走了
			ans += m - p[st - 1];
			print(p[st - 1], ',');
			for (int i = st - 1; i > 0; --i)
				ans += p[i] - p[i - 1],
				print(p[i - 1], ',');
		}
	}
	else {
		int st = upper_bound(all(p), m) - p.begin() - 1; // 找到第一个小于m的下标
		print(m, ',');
		if (st != -1) { // m 左边存在需要访问的柱面号
			ans += m - p[st];
			print(p[st], ',');
			for (int i = st; i > 0; --i)
				ans += p[i] - p[i - 1],
				print(p[i - 1], ',');
			if (st != n - 1)
				ans += p[st + 1] - p[0], // 移动到第一个大于m的下标处,注意可能不存在
				print(p[st + 1], ',');
			for (int i = st + 1; i < n - 1; ++i)
				ans += p[i + 1] - p[i],
				print(p[i + 1], ',');
		}
		else { // 直接向内走
			ans += m - p[st + 1];
			print(p[st + 1], ',');
			for (int i = st + 1; i < n - 1; ++i)
				ans += p[i + 1] - p[i],
				print(p[i + 1], ',');
		}
	}
	puts("");
	print(ans);
	return 0;
}

你可能感兴趣的:(操作系统)