操作系统实验(进程调度)

article/2025/10/29 3:36:59

操作系统实验(进程调度)

  • 一、实验目的
  • 二、实验内容
  • 三、实验准备
    • 3.1优先权算法
    • 3.2时间片轮转调度算法
  • 四、实验

一、实验目的

  1.1理解有关进程控制块、进程队列的概念。
  1.2掌握进程优先权调度算法和时间片轮转调度算法的处理逻辑。


二、实验内容

  2.1设计进程控制块PCB的结构,分别适用于优先权调度算法和时间片轮转调度算法。

  2.2建立进程就绪队列。

  2.3编制两种进程调度算法:优先权调度和时间片轮转调度。


三、实验准备

3.1优先权算法

  为了照顾紧迫型进程获得优先处理,引入了优先权调度算法。它从就绪队列中选择一个优先权最高的进程,让其获得处理器并执行。这时,又进一步把该算法分为两种方式。

3.1.1非抢占式优先权调度算法。
  在这种方式下,系统一旦把处理器分配给就绪队列中优先权最高的进程后,该进程就占有处理器一直运行下去,直到该进程完成或因发生事件而阻塞,才退出处理器。系统这时才能将处理器分配给另一个优先权高的进程。这种方式实际上是每次将处理器分配给当前就绪队列中优先权最高的进程。它常用于批处理系统中,也可用于某些对时间要求不严格的实时系统中。

3.1.2抢占式优先权调度算法。

  在这种方式下,系统同样把处理器分配给当前就绪队列中优先权最高的进程,使之执行。但在其执行期间,仍然会不断有新的就绪进程进入就绪队列,如果出现某个进程,其优先权比当前正在执行的进程的优先权还高时,进程调度程序就会立即暂停当前进程的执行而将处理器收回,并将处理器分配给新出现的优先权更高的进程,让其执行,这种方式实际上水远都是系统中优先权最高的进程占用处理器执行。因此,它能更好地满足紧迫进程的要求,故常用于要求比较严格的实时系统中,以及对性能要求较高的批处理和分时系统中。

  对于优先权调度算法,其关键在于是采用静态优先权,还是动态优先权,以及如何确定进程的优先权。


静态优先权:
  是在创建进程时确定的,并且规定它在进程的整个运行期间保持不变。一般来说,优先权是利用某个范围内的一个整数来表示的、如0~7,或0~255中的某个整数,所以又称为优先数。在使用时,有的系统用“0”表示最高优先权,数值越大优先权越小,而有的系统则恰恰相反。

动态优先权
  要配合抢占调度方式使用,它是指在创建进程时所赋予的优先权,可以随着进程的推进而发生改变,以便获得更好的调度性能。在就绪队列中等待调度的进程,可以随着其等待时间的增加,其优先权也以某个速率增加。因此,对于优先权初值很低的进程,在等待足够长的时间后,其优先权也可能升为最高,从而获得调度,占用处理器并执行。同样规定正在执行的进程,其优先权将随着执行时间的增加而逐渐降低,使其优先权可能不再是最高,从而暂停其执行,将处理器回收并分配给其他优先权更高的进程。这种方式能防止个别长期进程长期占用处理器的现象。

3.2时间片轮转调度算法

  在分时系统中,为了保证人机交互的及时性,系统使每个进程依次按时间片方式轮流地执行,即时间片轮转调度算法。在该算法中,系统将所有的就绪进程按进入就绪队列的先后次序排列。每次调度时把CPU分配给队首进程,让其执行一个时间片,当时间片用完,由计时器发出时钟中断,调度程序则暂停该进程的执行,使其退出处理器,并将它送到就绪队列的末尾,等待下一轮调度执行。然后,把CPU分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程,在一定的时间(可接受的等待时间)内,均能获得一个时间片的执行时间。
  在时间片轮转调度算法中,时间片的大小对系统的性能有很大影响。如果时间片太大,大到每个进程都能在一个时间片内执行结東,则时间片轮转调度算法退化为先来先服务调度算法,用户将不能获得满意的响应时间。若时间片过小,连用户键入的简单常用命令都要花费多个时间片,那么系统将频繁地进行进程的切换,同样难以保证用户对响应时间的要求。


四、实验

  1.同学们必须独立完成程序的调试和运行,记录运行结果并对结果进行分析;
  2.分析程序所定义使用的数据结构;
  3.分析程序的结构,并画出程序流程图;
  4.撰写分析报告


4.2数据类型定义:

1.1	数据结构
#include<conio.h>//getch函数输出
#define PSUM 3//进程数为3 
#define PTIME 30//进程时间为30 enum process_state
{ready,//就绪状态 execute,//执行状态 finish//完成状态 
};//定义进程状态struct lskpcb
{char name[4];//进程名int priority;//优先权int cputime;//CPU运行时间int needtime;//进程运行所需时间int count;//进程执行次数int round;//时间片轮转轮次int process;//进程状态struct lskpcb *next;//创建一个指针 
};// 定义进程创建的PCB

4.3 程序流程图如下图:

优先权流程图如下:
在这里插入图片描述
时间片轮转调度法程序流程图如下:
在这里插入图片描述

完整代码如下:

#include<stdio.h>
#include<conio.h>//getch函数输出 
#include<stdlib.h>
#include<iostream>
#include<windows.h>
#define PSUM 3//进程数为3 
#define PTIME 30//进程时间为30 enum process_state
{ready,//就绪状态 execute,//执行状态 finish//完成状态 
};//定义进程状态struct lskpcb
{char name[4];//进程名int priority;//优先权int cputime;//CPU运行时间int needtime;//进程运行所需时间int count;//进程执行次数int round;//时间片轮转轮次int process;//进程状态struct lskpcb *next;//创建一个指针 
};// 定义进程创建的PCBlskpcb *get_process()
{lskpcb *q;lskpcb *t;lskpcb *p;int i = 0;printf("请输入进程名和cpu运行时间:\n");while(i < PSUM){q=(struct lskpcb *)malloc(sizeof(struct lskpcb));scanf("%s", &(q -> name));scanf("%d", &(q -> needtime));q -> cputime = 0;q -> priority = PTIME - q -> needtime;q -> process = ready;q -> next = NULL;//指针默认值为空 if(i == 0){p = q;t = q;}else{t -> next = q;//创建就绪进程队列t = q;}i++;}//输入模拟测试的进程名和执行所需时间,初始设置可模拟5个进程的调度	return p;
}void display(struct lskpcb *p)
{printf("进程名""   ""cpu运行的时间""   ""还需要的时间""   " "优先权""   ""状态\n");while(p){printf("%s",p -> name); printf("            ");printf("%d",p -> cputime);printf("               ");printf("%d",p -> needtime);printf("            ");printf("%d",p -> priority);printf("     ");switch(p -> process)//进程状态循环 {case ready:printf("就绪\n",ready);break;case execute:printf("执行\n",execute);break;case finish:printf("完成\n",finish);break;}p = p->next;}//显示模拟结果,包含进程名、CPU时间、运行所需时间以及优先级
}int process_finish(lskpcb *q)
{int ks = 1;	while(ks && q){ks = ks && q -> needtime == 0;q = q -> next;}return ks;
}//结束进程,即将队列中各进程的所需时间设置为0void cpuexe(lskpcb *q)
{lskpcb *t = q;int tp = 0;while(q){if(q -> process != finish){q -> process = ready;	}if(q -> needtime == 0){q -> process = finish;}if(tp < q -> priority && q -> process != finish){tp = q -> priority;t = q;}q = q -> next;}if(t -> needtime != 0){t -> priority -= 2;t -> needtime --;t -> process = execute;t -> cputime ++;}
}//选择某一进程,给它分配CPU
//计算进程优先级void priority_cal()
{lskpcb *p;system("cls");//清屏函数 p = get_process();int cpu = 0;system("cls");while(!process_finish(p)){cpu++;printf("CPU运行时间:%d\n",cpu);cpuexe(p);display(p);getch();system("cls");}printf("全部优先权进程已运行完毕,请输入学号退出演示或者任意键进入主菜单选择界面:\n");getch();system("cls");
}void displaymenu()
{printf("******程序只用于模拟测试******\n"); printf("请使用者选择以下功能菜单:\n");printf("1.时间片轮法\n");printf("2.优先权调度\n");printf("3.退出请输入正确的指令:\n");
}//显示调度算法菜单,可供用户选择优先权调度算法和时间片轮转调度算法lskpcb *getprocess_round()
{lskpcb *q;lskpcb *t;lskpcb *p;int i = 0;printf("请输入进程名和时间\n");while(i<PSUM){q = (struct lskpcb * )malloc(sizeof(struct lskpcb));scanf("%s", &(q->name));scanf("%d", &(q->needtime));q -> cputime = 0;q -> round = 0;q -> count = 0;q -> process = ready;q -> next = NULL;if(i == 0){p = q;t = q;}else{t -> next = q;t = q;}i++;}return p;
}//时间片轮转调度算法创建就绪进程队列void cpu_round(lskpcb *q)
{q -> cputime += 1;//CPU时间加2 q -> needtime -= 1;//还需要的时间减2 if(q -> needtime < 0){q-> needtime = 0;}q -> count ++;q -> round ++;q -> process = execute;
}//采用时间片轮转调度算法执行某一进程lskpcb *get_next(lskpcb *L,lskpcb *H)
{lskpcb *t;t = L;do{t = t->next;}while(t && t -> process == finish);if(t == NULL){t = H;while(t -> next != L && t -> process == finish){t = t-> next;}}return t;
}//获取下一个进程void setstate(lskpcb *p)
{while(p){if(p -> needtime ==  0){p -> process = finish;//如果所需执行时间为0,则设置运行状态为结東}if(p -> process == execute){p -> process = ready;//如果为执行状态则设置为就绪}p = p -> next;}
}//设置队列中进程执行状态void display_round(lskpcb *p)
{printf("进程名" "   " "CPU运行时间" "   " "还需要的时间" "   " "时间片的次数" "   " "时间片进程轮次" "   " "状态\n");while(p){printf("%s", p -> name);printf("           ");printf("%d", p -> cputime);printf("                ");printf("%d", p -> needtime);printf("             ");printf("%d",p -> count);printf("               ");printf("%d",p -> round);printf("          ");switch(p -> process){case ready:printf("就绪\n",ready);break;case execute:printf("执行\n",execute);break;case finish:printf("完成\n",finish);break;}p  =  p -> next;}
}//时间片轮转调度算法输出调度信息void round_cal()
{lskpcb *p;lskpcb *r;system("cls");p = getprocess_round();int cpu = 0;system("cls");r = p;while(!process_finish(p)){cpu += 1;cpu_round(r);r = get_next(r,p);printf("CPU运行时间:%d\n",cpu) ;display_round(p);setstate(p);getch();system("cls");}printf("全部时间片进程已运行完毕,请输入任意键进入主菜单选择界面:\n");getch();//等待读取键盘字符 system("cls");
}//时间片轮转调度算法计算轮次及输出调度信息int main()
{displaymenu();while(true){int lsp = 0;int flag = 0;scanf("%d",&lsp);switch(lsp){case 1:round_cal();break;case 2:priority_cal();break;case 3:{printf("警告!!!!退出系统错误,需要输入正确的指令退出系统请重新输入:\n") ;break;}case 49:{flag = 1;break;}//退出系统的代码,当输入49口令时能正确退出系统 default:break;}if(flag == 1){break;}//当flag=1时跳出循环进入菜单选择模式 displaymenu(); }
}

运行结果如下:

  选择时间片轮转:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


http://chatgpt.dhexx.cn/article/bqF0xwLU.shtml

相关文章

【MFC】CCriticalSection类在Release编译下调用Lock函数会报0xC0000008错误

【MFC】CCriticalSection类在Release编译下调用Lock函数会报错0xC0000008 问题描述方法一 CRITICAL_SECTION代替CCriticalSection方法二 使用WaitForSingleObject和ReleaseMutex()结语 问题描述 通过以下伪代码方式描述问题&#xff1a; 主对话框类内创建成员变量及结构体变量…

联合使用类CCriticalSection和类CSingleLock同步线程

&#xff08;1&#xff09;新建一个控制台工程SellTicketTest2&#xff0c;并在向导的“应用程序设置”中勾选“MFC”。 &#xff08;2&#xff09;打开SellTicketTest2.cpp&#xff0c;在开头中引入头文件。 #include "afxmt.h"&#xff08;3&#xff09;添加变量&…

单独使用CCriticalSection对象来同步线程

&#xff08;1&#xff09;新建一个控制台工程SellTicketTest&#xff0c;并在向导的“应用程序设置”中勾选“MFC”&#xff0c;因为CCriticalSection属于MFC类&#xff0c;如图所示。 &#xff08;2&#xff09;在SellTicketTest.cpp开头中引入头文件。 #include "afx…

linux查看java线程死锁_ccriticalsection 多线程 死锁_c++ 线程死锁_linux 线程 死锁

qq_407283393122018-12-10 一个很蠢的造成死锁的问题 wanglt3113172018-12-12 什么是死锁&#xff0c;死锁的原因&#xff0c;如何避免 apanying902019-01-09 c3p0连接死锁 Cain_1507662016-09-20 notify产生死锁的场景(备忘) liuchuanyangyan9132017-02-23 C3P0配置错误导致的…

MFC线程同步—— CCriticalSection类使用

多个线程访问临界区时&#xff0c;可以使用临界区对象。临界区对象是一个独占性共享资源&#xff0c;任一时刻只有一个线程可以拥有临界区。拥有临界区的线程可以访问被保护起来的资源或代码段&#xff0c;其他希望进入临界区的线程将被挂起等待&#xff0c;直到拥有临界区的线…

CCriticalSection与CSingleLock

CCriticalSection An object of class CCriticalSection represents a “critical section” — a synchronization object that allows one thread at a time to access a resource or section of code. Critical sections are useful when only one thread at a time can be …

关键部分CCriticalSection使用

类CCriticalSection的对象表示一个“临界区”&#xff0c;它是一个用于同步的对象&#xff0c;同一时刻仅仅同意一个线程存取资源或代码区。临界区在控制一次仅仅有一个线程改动数据或其他的控制资源时很实用。比如&#xff0c;在链表中添加一个结点就仅仅同意一次一个线程进行…

模拟售票大厅实例——多线程时访问共享变量时的安全(CMutex或CCriticalSection的应用)

当程序运行时&#xff0c;可以通过多线程来提高程序运行的效率和拥有更好的体验。但多线程&#xff08;或多进程&#xff09;同时也带来很多的问题&#xff1a;最严重的莫过于对同一个对象或变量访问时&#xff0c;由于线程运行异步的原因&#xff0c;会造成程序运行出现无法控…

在MFC下面实际演示CCriticalSection 的使用

Q&#xff1a;CCriticalSection是什么&#xff1f; A&#xff1a;CCriticalSection是一种线程同步策略 或者说技术 或者方法 总之呢就是这么个意思。。。。 参考资料&#xff1a; http://blog.csdn.net/akof1314/article/details/5773076 http://www.cnblogs.com/hlxs/archi…

Android对话框总结(普通对话框,单选对话框,多选对话框,自定义对话框)

个人推荐: &#x1f4e2;&#x1f4e2;&#x1f4e2; 前些天发现了一个蛮有意思的人工智能学习网站,8个字形容一下 "通俗易懂&#xff0c;风趣幽默"&#xff0c;感觉非常有意思,忍不住分享一下给大家。点击跳转到教程。 一:AlterDialog对话框 二:普通对话框 运行效果…

Android对话框显示输入框

在弹出的对话框显示输入框有两种方法&#xff1a; 法一&#xff1a;新建一个布局&#xff0c;并在对话框中引用它。 法二&#xff1a;直接在Activity中定义Edit并在对话框中用getText方法得到输入信息。

Android对话框的使用

Android对话框的使用 对话框&#xff08;Dialog&#xff09;是Android系统在Activity或者其他组件运行过程中提供的一种提示机制。它可以帮助应用完成一些必要的提示功能&#xff0c;同时提供一些与用户交互的功能。 对话框分为很多种&#xff0c;下面将一一介绍…

android 自定义对话框

// 基础库 implementation com.github.goweii.AnyLayer:anylayer:2.5.0 // 通用弹窗&#xff08;依赖基础库&#xff09; implementation com.github.goweii.AnyLayer:anylayer-common:2.5.0 编写dialog_layout 布局 <?xml version"1.0" encoding"utf-8&qu…

Android对话框的使用总结

一&#xff0e;相关概念 一个对话框一般是一个出现在当前Activity之上的一个小窗口. 处于下面的Activity失去焦点, 对话框接受所有的用户交互. 对话框一般用于提示信息和与当前应用程序直接相关的小功能. Android API 支持下列类型的对话框对象: &#xff08;一&#x…

Android对话框控件读写,Android 对话框控件

对话框控件 一、概述 对话框是 UI 设计中常用的控件&#xff0c;在windows操作系统中&#xff0c;对话框可分为模式对话框和非模式对话框。 模式对话框在使用时&#xff0c;项目中其它UI是不允许操作的&#xff0c;如保存对文件话框 非模式对话框允许操作其它的 UI Android 的对…

Android对话框总结

一、什么是对话框&#xff1f; 一种次要窗口&#xff0c;包含按钮和各种选项&#xff0c;通过它们可以完成特定命令或任务。 查找和替换对话框 对话框与窗口有区别&#xff0c;它没有最大化按钮、没有最小化按钮、大都不能改变形状大小。&#xff08;“打开文件”对话框是可以改…

Android常用对话框

学习目标&#xff1a; 两周入门Android 学习内容&#xff1a; 常见对话框: 对话框是程序与用户交互的一种方式&#xff0c;通常用于显示当前程序提示信息以及相关说明,以小窗口形式展现 普通对话框&#xff1a; 通过AlertDialog.Builder(this).create来创建对话框最后通过…

了解Android布局,了解Android对话框布局

我正在为我的android应用程序做一个简单的自定义对话框&#xff0c;只显示一个搜索栏。然而&#xff0c;这个简单任务的复杂性让我很烦。了解Android对话框布局 我的对话框布局如下&#xff1a;在代码中创建 android:orientation"vertical" android:layout_width&quo…

Android对话框(普通对话框、单选对话框、多选对话框、进度条对话框)

一、普通对话框 // 通过builder 构建器来构造AlertDialog.Builder builder = new Builder(this);builder.setTitle("警告");builder.setMessage("你好么 ");builder.setPositiveButton("好", new OnClickListener() {@Overridepublic void onCl…

android 对话框窗口,Android 对话框详解(一)

对话框是程序运行中的弹出窗口。例如&#xff0c;当用户要删除一个联系方式时&#xff0c;会弹出一个 对话框&#xff0c;让用户确认是否真的要删除。 Android系统提供了四种对话框:警告对话框 (AlertDialog)、进度对话框(ProgressDialog)、日期选择对话框(DatePickerDialog)和…