进程控制与进程调度 —— 时间片轮转调度算法(C++版)

目录

实验一  进程控制与进程调度

一、实验目的

二、实验内容 

三、数据结构及符号说明 

四、运行环境说明

五、代码段 

六、 效果展示


实验一  进程控制与进程调度

备注:大二(下)操作系统实验一 

一、实验目的

掌握进程状态的转变、进程调度的策略

理解进程控制的过程,进一步体会多道程序并发执行的特点

二、实验内容 

利用简单的结构和控制方法模拟进程结构、进程状态和进程控制,进程调度采用时间片轮转调度算法

1、用PCB表示进程实体,利用随机数方法或键盘控制方法模拟进程执行中产生的事件,或者基于图形界面控制进程

2、定义PCB包括基本内容,如内部ID、外部ID、进程状态、队列指针

由于很难实现真正的进程创建功能,在实验中只需建立PCB节点,并用它代表一个完整的进程

每创建一个进程时,可动态分配PCB节点,对相应内容赋值,并链接到对应队列

可参考如下数据结构(C语言实现):

struct PCB

{

      int inid;                 //内部ID  自动生成

      char outid[10];     //外部ID

      int  state ;             //进程状态  0表示执行状态  1表示就绪状态  2表示阻塞状态

      struct PCB*next;

};

struct PCB *ready,*blocked,*running;

3、定义进程状态转换方式

真实的进程状态转换是由进程内部操作或操作系统的控制引起

由于模拟程序中无法实现这些功能,实验可以采用随机数方法或键盘控制方法模拟,并实现对应的控制程序

随机方法指产生1-5的随机数,分别代表(1)创建进程、(2)时间片到、(3)进程阻塞、(4)唤醒进程、(5)结束进程等事件;

键盘模拟方法指定义5个选项菜单代表以上5种事件

4、根据随机数或键盘操作处理就绪队列、阻塞队列和当前执行进程的状态

每次事件处理后应显示出当前系统中的执行进程是哪一个,就绪队列和阻塞队列分别包含哪些进程

5、编程语言不限,可以选择用C语言、Python或java

三、数据结构及符号说明 

数据结构:
使用结构体PCB来表示一个进程

使用链表实现就绪队列和阻塞队列,指针为 PCB * next
符号说明:
就绪队列头指针 ready_head

就绪队列尾指针 ready_tail
阻塞队列头指针 blocked_head
阻塞队列尾指针 blocked_tail
当前运行程序指针 running
 

四、运行环境说明

五、代码段 

#include<iostream>
#include<unordered_set>
using namespace std;

int inID;
unordered_set<string> S;

struct PCB
{
	int in_id;     // 内部id 
	string out_id; // 外部id 
	int state;     // 进程状态  0表示执行状态,1表示就绪状态,2表示阻塞状态
	PCB * next;    // next指针 
};

PCB * ready_head, * ready_tail, * blocked_head, * blocked_tail, * running;

PCB * PCB_creat() // 创建PCB 
{
	PCB * p = new PCB;
	cout << "进程创建成功!" << endl;
	return p;
}

void PCB_init(PCB * p) // 初始化PCB 
{
	string id;
	p -> in_id = inID ++ ;
	cout << "请输入进程外部ID:" << endl;
	cin >> id;
	while(S.count(id))
	{
		cout << "您输入的外部ID已被使用,请重新输入!" << endl;
		cin >> id;
	}
	S.insert(id);
	p -> out_id = id;
	p -> state = 1;
	p -> next = NULL;
	cout << "进程初始化成功!" << endl << endl;
}

int insert_into_ready(PCB * p) // 插入就绪队列
{
		p -> next = NULL;
		if(ready_tail) ready_tail -> next = p;
		ready_tail = p;
		if(! ready_head) ready_head = p;
		return 0;
}

void insert_into_blocked(PCB * p) // 插入阻塞队列 
{
	p -> next = NULL;
	if(blocked_tail) blocked_tail -> next = p;
	blocked_tail = p;
	if(! blocked_head) blocked_head = p;
}

void change_process() // 切换进程 
{
	// 将正在运行的进程插入就绪队列
	if(running) insert_into_ready(running);
	
	// 调度就绪队列队首进程
	running = ready_head;
	
	if(ready_head) ready_head = ready_head -> next;
	if(ready_head == NULL) ready_tail = NULL;
	
	cout << "切换进程成功!" << endl << endl;
}

void block_process() // 阻塞进程
{
	if(running) 
	{
		// 将正在运行的进程插入阻塞队列
		insert_into_blocked(running); 
		
		// 调度就绪队列队首进程
		running = ready_head;
		
	    if(ready_head) ready_head = ready_head -> next;
	    if(ready_head == NULL) ready_tail = NULL;
		cout << "进程阻塞成功!" << endl << endl;
	}
	
	else cout << "当前系统没有运行当中的程序可供阻塞!" << endl << endl;
}

void awaken_process() // 唤醒进程 
{
	if(blocked_head)
	{
		auto p = blocked_head -> next;
		// 注意需要临时存储blocked_head -> next
		// 因为insert_into_ready(blocked_head);会将blocked_head -> next修改为NULL
		
		// 将阻塞队列首进程插入就绪队列 
		insert_into_ready(blocked_head);
		
		blocked_head = p;
		if(blocked_head == NULL) blocked_tail = NULL;
		cout << "成功唤醒阻塞队列队首进程!" << endl << endl;
	}
	
	else cout << "阻塞队列为空,没有可供唤醒的进程!" << endl << endl;
}

void end_process() // 结束进程 
{
	if(running)
	{
		S.erase(running -> out_id);
		delete running;
		running = ready_head;
		
	    if(ready_head) ready_head = ready_head -> next;
	    if(ready_head == NULL) ready_tail = NULL;
	    cout << "成功结束当前运行进程!" << endl << endl;
	}
	
	else cout << "当前系统没有运行当中的程序可供结束!" << endl << endl;
}

void show() // 显示 
{
	if(running) cout << "运行的程序是:" << running -> out_id << endl;
	else cout << "没有正在运行的程序!" << endl;
	
	if(ready_head)
	{
		cout << "就绪队列为:" ; 
		for(auto i = ready_head; i; i = i -> next)
		  cout << i -> out_id << " " ;
		cout << endl;
	}
	else cout << "就绪队列为空!" << endl;
	
	if(blocked_head)
	{
		cout << "阻塞队列为:" ; 
		for(auto i = blocked_head; i; i = i -> next)
		  cout << i -> out_id << " " ;
		cout << endl;		
	}
	else cout << "阻塞队列为空!" << endl;
	
	cout << endl;
}

void check() // 检查
{
	if(!running && ready_head)
	  {
	  	 running = ready_head;
	  	 ready_head = ready_head -> next;
	  }
	// 若当前没有正在运行的进程且当前就绪队列非空,则调度就绪队列队首进程
}

int main()
{
	while(true)
	{
		int choice; 
		cout << "请选择系统模拟选项:" << endl;
		cout << "1、创建进程" << endl;
		cout << "2、当前时间片结束" << endl;
		cout << "3、阻塞当前运行进程" << endl;
		cout << "4、唤醒阻塞队列队首进程" << endl;
		cout << "5、结束当前运行进程" << endl;
		cout << "6、退出系统" << endl << endl;
		cin >> choice;
		
		switch(choice)
		{
			case 1: 
			    {
			        auto p = PCB_creat();
			        PCB_init(p); 
			        insert_into_ready(p);
			        check();
					show(); 
					break; 
			    }
			case 2: change_process(); show(); break; 
			case 3: block_process(); show(); break; 
			case 4:awaken_process(); check(); show(); break; 
			case 5:end_process(); show(); break; 
			case 6: exit(0);
			default: cout << "您的选择有误,请重新选择!" << endl;
		}
	}
	
	return 0;
}

六、 效果展示

  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于进程调度算法按优先级以及时间片轮转的实现,我可以给您提供一些思路。 首先,我们需要定义一个进程控制块(PCB)结构体,用来存储每个进程的相关信息,包括进程ID、进程状态、优先级、已运行时间等等。例如: ```c++ struct PCB { int pid; // 进程ID int priority; // 优先级 int runtime; // 已运行时间 int burst_time; // 还需要运行的时间 // 其他信息... }; ``` 然后,我们需要定义一个进程调度器类,用来实现按优先级和时间片轮转调度算法。该类需要维护一个进程队列,按照优先级从高到低排序。每次调度时,从队列头部取出一个进程,执行一定时间片(比如说10ms),然后放回队列尾部。如果该进程的运行时间超过了它的时间片,那么将它放回队列头部,等待下一次调度。如果该进程已经运行完毕,那么将它从队列中删除。 具体实现可以参考下面的代码: ```c++ #include <queue> #include <vector> struct PCB { int pid; // 进程ID int priority; // 优先级 int runtime; // 已运行时间 int burst_time; // 还需要运行的时间 // 其他信息... }; class Scheduler { public: void add_process(PCB process) { // 将进程按照优先级插入队列 auto it = std::lower_bound(processes.begin(), processes.end(), process, [](const PCB& a, const PCB& b) { return a.priority > b.priority; }); processes.insert(it, process); } int run_process(int time_slice) { int pid = -1; if (processes.empty()) { return pid; } // 取出队列头部进程 PCB process = processes.front(); processes.pop_front(); // 执行一定时间片 process.runtime += time_slice; process.burst_time -= time_slice; if (process.burst_time <= 0) { // 进程已经运行完毕 pid = process.pid; } else { // 将进程放回队列 processes.push_back(process); } return pid; } private: std::deque<PCB> processes; // 进程队列 }; ``` 在上面的代码中,我们使用了 STL 中的 `deque`(双端队列)来实现进程队列,并且使用了 `lower_bound` 算法来按照优先级插入进程。在 `run_process` 方法中,我们执行了一定时间片后判断了进程是否已经运行完毕,并且如果进程还未运行完毕,将其放回队列尾部。 希望可以帮到您!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值