操作系统实验-进程控制

进程控制

●基本要求:模拟操作系统内核对进程的控制和管理:包括进程的创建和撤销、进程状态的切换和简单的内存空间管理。

●参考学时:6学时

●实验提示:

  1. 定义管理每个进程的数据结构PCB:包含进程名称、队列指针、分配的物理内存区域(基址和长度)。每创建一个进程时,需要为其创建PCB并分配空闲内存空间,对PCB进行初始化,并加入就绪队列。(斜体为可选)

可参考如下数据结构(动态形式):

struct PCB{

   char name[8];

   struct PCB *next;

   ...

};

struct PCB *ready,*blocked,*running;

创建进程时申请空白PCB:

struct PCB *p=(struct PCB *)malloc(sizeof(struct PCB));

并把新建进程的PCB添加到就绪队列末尾:

add(ready,p);

其中,ready为就绪队列头节点,并在开始处分配了空间;add函数是链表中添加节点函数,代码参考如下:

void add(struct PCB *head, struct PCB *process){

   struct PCB *tmp=head;

   while(tmp->next!=NULL)

       tmp=tmp->next;

   tmp->next=process;

   process->next=NULL;

}

  1. 模拟触发进程状态转换的事件:采用键盘控制方法来模拟触发进程状态切换的事件(例如输入1代表创建新进程、2执行进程时间片到、3阻塞执行进程、4唤醒第一个阻塞进程、5终止执行进程),实现对应的控制程序。
  2. 根据当前发生的事件对进程的状态进行切换,并显示出当前系统中的执行队列、就绪队列和阻塞队列。
  3. *(选做)完成可变分区的分配与回收,创建进程的同时申请一块连续的内存空间,在PCB中设置好基址和长度,结束进程时回收分配的内存空间。分配可采用首次适应、最佳适应或最差适应算法,碎片大小为2Kb,最后回收所有进程的空间,对空间分区的合并。可以查看进程所占的空间和系统空闲空间。
  4. 可以用一个链表(如图1-1所示)来维护已分配的和空闲的内存段,其中一个段或者包含一个进程,或者是两个进程之间的空闲段。 在图1-1中,链表的每一项包含四个值域。第一个值域表示内存段是空闲或占用(例如,空闲段用H表示,进程占用的段用P表示);第二个值域表示内存段的起始位置,第三个值域表示内存段的长度;第四个值域为指向链表下一项的指针。该链表按照内存段的起始地址进行从小到大排序。这样排序的好处是方便内存空间的回收。一个要终止的进程一般会有两个邻居(除了在内存顶端和内存底端的进程)。邻居可能是进程也可能是空闲段。根据两个邻居的不同类型,可以分为四种回收情况(如图1-2所示)。在图1-2(a)中,对链表的更新只需要将P置为H;在图1-2(b)和(c)中,需要将P置为H,并将该项与另外一个相邻的空闲段的项合并为一项;在图1-2(d)中,需要将该项和两个邻居合并为一项。考虑到合并空闲段需要查看邻居,因此用双向链表会比单向链表更加方便。

图 1-1. (a) 内存空间的示例,有5个进程和3个空闲段,阴影部分表示空闲段。

(b) 管理内存空间的链表

图 1-2. 对终止的进程X的四种内存回收情况(阴影代表空闲区)

代码

#include<iostream>
#include<queue>
#include<string>
#include<sstream>
#include<list>
using namespace std;

//PCB
class PCB {
public:
	string name;
	int base;//基址
	int length;//长度
};

//内存块
class Memory_Block {
public:
	char state;//状态,H表示空闲,P表示占用
	int base;//基址
	int length;//长度
};

//状态队列
queue<PCB> ready;
queue<PCB> run;
queue<PCB> blockage;//阻塞

//内存管理
list<Memory_Block> memory;

void help();
bool creat(string name, int length);
void close();
void timeslice_end();
void clogging();
void awaken();
void view(int flag);

int main() {
	cout<< "This is a programe to show how the processes work!\nIt is made by Gin.\nYou can see the Help by commend 'H'!\n\nPlease input two number instead of the begin and the size!\n";
	int begin, size;
	cin >> begin >> size;
	getchar();
	memory.push_back({ 'H',begin,size });
	cout << "You have successfully create a new memory!\n";
	string directives="";//指令
	while (directives != "Q" || directives != "q") {
		cout << ">";
		//cin.ignore(100, '\n');
		cin >> directives;
		getchar();
		if (directives == "H" || directives == "h") {
			help();
		}
		else if (directives[0] == 'c' || directives[0] == 'C') {
			string name;
			int length;
			cin >> name >> length;
			creat(name, length);
			getchar();
		}
		else if (directives == "Q" || directives == "q") {
			return 0;
		}
		else if (directives == "E" || directives == "e") {
			close();
		}
		else if (directives == "T" || directives == "t") {
			timeslice_end();
		}
		else if (directives == "B" || directives == "b") {
			clogging();
		}
		else if (directives == "W" || directives == "w") {
			awaken();
		}
		else if (directives == "s1" || directives == "s2" || directives == "S1" || directives == "S2") {
			if (directives == "s1" || directives == "S1") {
				view(1);
			}
			else {
				view(2);
			}
			
		}
		else {
			cout << "Wrong commend!\n";
		}
	}
}

void help() {
	cout << "命令使用:\n1.创建:C / c + 空格 + 进程名字 + 进程大小.\n2.调度 : (要求自动).\n3.终止 : E / e 结束正在运行的进程.\n4.时间片到 : T / t : 将运行的进程装入就绪队列尾部, 将下一个自动调度过来.\n5.阻塞 : B / b 将正在执行的程序阻塞, 即插入阻塞队列尾部.\n6.唤醒 : W / w 将阻塞队列中的一个进程调度到就绪队列上, 即阻塞队列头到就绪队列尾.\n7.查看 : 随时查看队列的情况 : S / s(Show) 1 / 2.(s1 查看的是三个进程队列的情况,s2查看的是剩余内存的情况)\n8.退出:Q / q.\n";
}

bool creat(string name, int length) {
	queue<PCB> temp = ready;
	while (!temp.empty()) {
		if (temp.front().name == name) {
			cout << "The process s has exist,and you can see where it is by commend '" << name << "'\n";
			return false;
		}
		temp.pop();
	}
	temp = run;
	while (!temp.empty()) {
		if (temp.front().name == name) {
			cout << "The process s has exist,and you can see where it is by commend '" << name << "'\n";
			return false;
		}
		temp.pop();
	}
	temp = blockage;
	while (!temp.empty()) {
		if (temp.front().name == name) {
			cout << "The process s has exist,and you can see where it is by commend '" << name << "'\n";
			return false;
		}
		temp.pop();
	}
	for (auto i = memory.begin(); i != memory.end(); i++) {
		if (i->state == 'H' && i->length >= length) {
			PCB pcb;
			if (length + 2 >= i->length) {
				i->state = 'P';
				pcb.name = name;
				pcb.base = i->base;
				pcb.length = i->length;
			}
			else {
				i->state = 'P';
				Memory_Block mb;
				mb.state = 'H';
				mb.base = i->base+length;
				mb.length = i->length-length;
				i->length = length;
				if (next(i) != memory.end()) {
					memory.emplace(next(i), mb);
				}
				else {
					memory.push_back(mb);
				}
				
				pcb.name = name;
				pcb.base = i->base;
				pcb.length = length;

			}
			cout << "You successfully create a process named " << name << ".\n";

			if (run.size() == 0) {
				run.push(pcb);
			}
			else {
				ready.push(pcb);
			}
			return true;
		}
	}
	cout << "There is no memory for this process,create Fail!\n";
	return false;
}

void close() {
	string name;
	if (run.size() == 0) {
		cout << "There is no running process!\n";
		return;
	}
	else {
		name = run.front().name;
		PCB pcb=run.front();
		run.pop();
		if (ready.size() != 0) {
		    PCB pcb2 = ready.front();
			ready.pop();
			run.push(pcb2);
		}
		for (auto it = memory.begin(); it != memory.end();it++) {
			if (it->state=='P'&&it->base==pcb.base&&it->length==pcb.length) {
				it->state = 'H';
				
				if (it != memory.begin()) {
					if (prev(it)->state == 'H') {
						prev(it)->length += it->length;
						auto temp = prev(it);
						memory.erase(it);
						it = temp;
					}
				}
				if (next(it) != memory.end()) {
					if (next(it)->state == 'H') {
						it->length += next(it)->length;
						memory.erase(next(it));
					}
				}
				cout << "Process named " << name << " has been killed.\n";
				return;
			}
		}	
	}
}

void timeslice_end() {
	if (ready.size() == 0) {
		cout << "There is no running process!\n";
	}
	else {
		PCB pcb = run.front();
		run.pop();
		PCB pcb2 = ready.front();
		ready.pop();
		ready.push(pcb);
		run.push(pcb2);
		cout << "Process named " << pcb.name << "'s time is over.\n";
	}
}

void clogging() {
	if (run.size() == 0) {
		cout << "There is no running process!\n";
	}
	else {
		PCB pcb = run.front();
		run.pop();
		blockage.push(pcb);
		cout << "Process named " << pcb.name << " has been blocked.\n";
	}
	if (ready.size() != 0) {
		PCB pcb2 = ready.front();
		ready.pop();
		run.push(pcb2);
	}
}

void awaken() {
	if (blockage.size() == 0) {
		cout << "There is no blocking process!\n";
	}
	else {
		PCB pcb = blockage.front();
		blockage.pop();
		if (run.size() == 0) {
			run.push(pcb);
		}
		else {
			ready.push(pcb);
		}
		cout << "Process named " << pcb.name << " has been waked up.\n";
		
	}
}

void view(int flag) {
	if (flag == 1) {//s1
		cout << "The information will be showed in name(begin,size)\n";
		cout << "Ready Processes :";
		queue<PCB> temp = ready;
		while(!temp.empty()){
			cout << temp.front().name << "(" << to_string(temp.front().base) << "," << to_string(temp.front().length) << ") ";
			temp.pop();
		}
		cout << endl;
		temp = run;
		cout << "Executing Processes :";
		while (!temp.empty()) {
			cout << temp.front().name << "(" << to_string(temp.front().base) << "," << to_string(temp.front().length) << ") ";
			temp.pop();
		}
		cout << endl;
		temp = blockage;
		cout << "Blocking Processes :";
		while (!temp.empty()) {
			cout << temp.front().name << "(" << to_string(temp.front().base) << "," << to_string(temp.front().length) << ") ";
			temp.pop();
		}
		cout << endl;
	}
	else {//s2
		cout << "The left memory:\n";
		for (auto i : memory) {
			if (i.state == 'H') {
				cout << "Start:" << to_string(i.base) << "," << "Size:" << to_string(i.length) << "\n";
			}
		}
	}
}

效果截图 

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值