操作系统实验指导书2013(梁宝华)
- 格式:doc
- 大小:462.50 KB
- 文档页数:30
中央民族大学操作系统实验指导书目录前言 (3)实验总体要求 (4)实验格式 (5)实验一:Linux的初步认识 (6)实验二: 系统调用实验 (9)实验三:进程同步实验 (16)实验四:进程通信实验 (21)实验五:页面调度算法模拟 (28)实验六:虚拟文件系统 (31)实验七:Linux Socket编程 (79)附加实验:linux的深入认识 (86)前言《操作系统》课程是计算机科学与技术专业的主干课。
操作系统是现代计算机系统中必不可少的基本系统软件,对计算机系统资源实施管理,是所有其他软件与计算机硬件的唯一接口,所有用户在使用计算机时都要得到操作系统提供的服务。
《操作系统》课程是一门理论和实践相结合的课程。
通过《操作系统》实验教学,可以是使学生深入地掌握操作系统的基本概念、基本原理,同时也可以使学生能够运用《操作系统》提供的方法与技巧对实际问题进行算法设计和程序设计,即能更好地实现与课程同步练习,又进一步深化理解和灵活掌握教学内容;又能培养学生程序设计及上机调试的能力。
这将为其后继课程如《计算机体系结构》、《计算机网络》等打下必要的基础,同时也为今后在相关领域开展工作打下坚实的基础。
《操作系统》课程含有18学时的实验内容,要求学生完成linux的初步认识、进程同步、进程通信、页面调度算法模拟等实验,使学生了解和掌握操作系统的基本原理,掌握常用操作系统的使用和一般的管理方法等内容。
通过《操作系统》实践环节,培养学生认真分析问题、解决问题的能力,同时培养学生面对问题勤于思考及团队合作的意识,最终使学生达到理论与实践相结合的目的。
《操作系统》实验教学计划安排7个实验项目。
由于每个项目都是一个综合训练,仅仅依靠上机三个学时是远远不够的,尤其是实验6和实验7,具有很大的难度,教师可以根据学生的实际情况调整实验内容。
这里要求每个同学上实验课前必须做好充分的准备,如问题的分析、数据类型和系统的设计以及程序的编写、初步的调试等等,上机实验课主要是教师和同学们一起讨论和交流,共同解决系统设计和调试中的问题。
操作系统实验指导目录实验一 Windows2000进程观测 (1)实验二 Windows2000进程控制 (6)实验三Windows2000线程的运行 (14)实验四Windows2000线程同步 (19)实验五经典同步问题的实现 (27)实验六Windows2000内存管理 (31)实验七Windows2000文件管理 (40)实验八安装Linux操作系统 (48)实验九Linux 基本操作 (49)实验十Linux下的进程与线程 (55)实验一 Windows2000进程观测一、背景知识Windows 2000可以识别的应用程序包括控制台应用程序、GUI应用程序和服务应用程序。
控制台应用程序可以创建GUI,GUI应用程序可以作为服务来运行,服务也可以向标准的输出流写入数据。
不同类型应用程序间的惟一重要区别是其启动方法。
Windows 2000是以NT的技术构建的,它提供了创建控制台应用程序的能力,使用户可以利用标准的C++工具,如iostream库中的cout和cin对象,来创建小型应用程序。
当系统运行时,Windows 2000的服务通常要向系统用户提供所需功能。
服务应用程序类型需要ServiceMail() 函数,由服务控制管理器(SCM) 加以调用。
SCM是操作系统的集成部分,负责响应系统启动以开始服务、指导用户控制或从另一个服务中来的请求。
其本身负责使应用程序的行为像一个服务。
通常,服务登录到特殊的LocalSystem账号下,此账号具有与开发人员创建的服务不同的权限。
当令C++ 编译器创建可执行程序时,编译器将源代码编译成OBJ文件,然后将其与标准库相链接。
产生的EXE文件是装载器指令、机器指令和应用程序的数据的集合。
装载器指令告诉系统从哪里装载机器代码。
另一个装载器指令告诉系统从哪里开始执行进程的主线程。
在进行某些设置后,进入开发者提供的main() 、ServiceMain() 或WinMain() 函数的低级入口点。
操作系统实验指导书实验概述本次操作系统实验是为了让学生通过实践了解操作系统的基本概念,原理和使用。
通过完成实验,学生将了解操作系统内核,进程调度,文件系统和输入输出等关键组成部分。
实验环境实验要求使用 Linux 操作系统,可以选择任意一种 Linux 发行版。
可以在物理机上安装 Linux,也可以使用虚拟机软件(如 VirtualBox)来运行 Linux 虚拟机。
实验准备在进行实验之前,需要完成以下准备工作:1.安装 Linux 操作系统(如 Ubuntu、Fedora 等)或虚拟机软件(如VirtualBox)。
2.熟悉 Linux 基本命令和操作,包括文件操作、进程管理等。
实验内容本次操作系统实验分为以下几个部分:1. 实验一:进程管理本部分实验要求学生了解进程管理的基本概念和原理,掌握进程创建、终止和状态转换等操作。
学生需要完成以下任务:•编写一个简单的 C 程序,实现进程的创建、终止和状态转换功能。
•使用 Linux 命令行工具编译、运行和调试 C 程序。
•观察和分析进程的状态转换过程。
2. 实验二:进程调度本部分实验要求学生了解进程调度算法的原理和实现方法,掌握优先级调度、轮转调度和最短作业优先调度等算法。
学生需要完成以下任务:•编写一个简单的 C 程序,模拟进程调度算法的执行过程。
•使用 Linux 命令行工具编译、运行和调试 C 程序。
•观察和分析不同调度算法对进程执行顺序的影响。
3. 实验三:文件系统本部分实验要求学生了解文件系统的基本概念和实现原理,掌握文件的创建、读写和删除等操作。
学生需要完成以下任务:•编写一个简单的 C 程序,实现文件的创建、读写和删除功能。
•使用 Linux 命令行工具编译、运行和调试 C 程序。
•观察和分析文件系统的存储结构和操作过程。
4. 实验四:输入输出本部分实验要求学生了解操作系统的输入输出机制和设备驱动程序的原理和实现方法,掌握文件读写、设备驱动和错误处理等操作。
操作系统教程实验指导书目录实验一WINDOWS进程初识 (4)1、实验目的 (4)2、实验内容和步骤 (4)3、实验结论 (5)4、程序清单 (5)实验二进程管理 (8)背景知识 (8)1、实验目的 (11)2、实验内容和步骤 (11)3、实验结论 (13)4、程序清单 (13)实验三进程同步的经典算法 (18)背景知识 (18)1、实验目的 (19)2、实验内容和步骤 (19)3、实验结论 (20)4、程序清单 (21)实验四存储管理 (25)背景知识 (25)1、实验目的 (29)2、实验内容和步骤 (29)3、实验结论 (35)4、程序清单 (35)实验五文件和设备管理 (40)背景知识 (40)1、实验目的 (42)2、实验内容与步骤 (42)3、实验结论 (45)试验六文件系统设计试验 (46)1、试验目的 (46)2、实验内容与步骤 (46)3、实验结论 (46)4、对试验的改进以及效果 (47)附录A:参考程序 (49)附录B:文件系统模拟程序 (52)52实验一WINDOWS进程初识1、实验目的(1)学会使用VC编写基本的Win32 Consol Application(控制台应用程序)。
(2)掌握WINDOWS API的使用方法。
(3)编写测试程序,理解用户态运行和核心态运行。
2、实验内容和步骤(1)编写基本的Win32 Consol Application步骤1:登录进入Windows,启动VC++ 6.0。
步骤2:在“FILE”菜单中单击“NEW”子菜单,在“projects”选项卡中选择“Win32 Consol Application”,然后在“Project name”处输入工程名,在“Location”处输入工程目录。
创建一个新的控制台应用程序工程。
步骤3:在“FILE”菜单中单击“NEW”子菜单,在“Files”选项卡中选择“C++ Source File”, 然后在“File”处输入C/C++源程序的文件名。
OS操作系统课程实验指导书附运行截图实验1使用动态优先权的进程调度算法的模拟1、实验目的(1)加深对进程概念的理解(2)深入了解系统如何组织进程,创建进程(3)进一步认识如何实现处理机调度2、实验内容(1)实现对N个进程采用动态优先权优先算法的进程调度。
(2)每个用来标识进程的进程控制块PCB用结构来描述,包括以下字段:进程标识数ID。
进程优先数PRIORITY,并规定优先数越大的进程,其优先权越高。
进程已占用的CPU时间CPUTIME。
进程还需占用的CPU时间ALLTIME。
当进程运行完毕时,ALLTIME变为0。
进程的阻塞时间STARTBLOCK,表示当进程再运行STARTBLOCK 个时间片后,将进入阻塞状态。
进程被阻塞的时间BLOCKTIME,表示已阻塞的进程再等待BLOCKTIME个时间片后,将转换成就绪状态。
进程状态STATE。
队列指针NEXT,用来将PCB排成队列。
(3)优先数改变的原则:进程在就绪队列中停留一个时间片,优先数加1。
进程每运行一个时间片,优先数减3。
(4)假设在调度前,系统中有5个进程,它们的初始状态如下:ID 0 1 2 3 4PRIORITY 9 38 30 29 0CPUTIME 0 0 0 0 0ALLTIME 3 3 6 3 4STARTBLOCK 2 -1 -1 -1 -1BLOCKTIME 3 0 0 0 0STATE ready ready ready ready ready(5)为了清楚的观察各进程的调度过程,程序应将每个时间片内的情况显示出来,参照的具体格式如下:RUNNING PROG:i READY-QUEUE:->id1->id2BLOCK-QUEUE:->id3->id4= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = == = =ID 0 1 2 3 4PRIORITY P0 P1 P2 P3 P4CUPTIME C0 C1 C2 C3 C4ALLTIME A0 A1 A2 A3 A4STARTBLOCK T0 T1 T2 T3 T4BLOCKTIME B0 B1 B2 B3 B4STATE S0 S1 S2 S3 S43、实验结果(给出编写的程序源代码和运行结果的截图)【程序代码】#include#include#define N 5// 进程状态enum STATE { Ready, Run, Block, Finish };// PCB数据结构struct PCB {int id; // 标志数int priority; // 优先数int cpuTime; // 已占CPU时间int allTime; // 还需占CPU时间int blockTime; // 已被阻塞的时间int startBlock; // 开始阻塞时间STATE state; // 进程状态PCB *pre; // PCB的前指针PCB *nxt; // PCB的后指针};int id[N] = {0, 1, 2, 3, 4};int priority[N] = {9, 38, 30, 29, 0};int cpuTime[N] = {0, 0, 0, 0, 0};int allTime[N] = {3, 3, 6, 3, 4};int startBlock[N] = {2, -1, -1, -1, -1};int blockTime[N] = {3, 0, 0, 0, 0};void QuePush(PCB *process, PCB *queHead){process->pre = NULL;process->nxt = queHead->nxt;if (queHead->nxt != NULL) {queHead->nxt->pre = process;}queHead->nxt = process;}void quePop(PCB *process, PCB *queHead){if (process->pre != NULL) {process->pre->nxt = process->nxt;} else {queHead->nxt = process->nxt;}if (process->nxt != NULL) {process->nxt->pre = process->pre;}process->pre = process->nxt = NULL;}void queWalk(PCB *queHead){PCB *pro = queHead->nxt;if (pro == NULL) {printf("(没有进程啦)\");return;}while (pro != NULL){printf("id: %d, priority: %d, cpuTime: %d, alltime: %d,blockTime: %d,state:%d,startblock: %d\", pro->id, pro->priority, pro->cpuTime, pro->allTime, pro->blockTime, pro->state, pro->startBlock);pro = pro->nxt;}}int readyQueNum; // 就绪队列的进程数量PCB readyQueHead; // 就绪队列的头部PCB *readyMaxProcess; // 就绪队列中优先级最高的进程void readyQuePush(PCB *process){readyQueNum ++;process->state = Ready;QuePush(process, &readyQueHead);}PCB* readyQuePop(){readyQueNum --;quePop(readyMaxProcess, &readyQueHead);return readyMaxProcess;}// 每个时间片,更新就绪队列里进程的信息void readyQueUpdate(){int maxPriority = -1;PCB *pro = readyQueHead.nxt;if (pro == NULL) {// 就绪队列没有进程readyMaxProcess = NULL;return;}while (pro != NULL){pro->priority ++;if (pro->priority > maxPriority) {maxPriority = pro->priority;readyMaxProcess = pro;}pro = pro->nxt;}}// 返回就绪队列最高优先级的值int readyMaxPriority(){return readyMaxProcess->priority;}// 查看就绪队列里进程的信息void readyQueWalk(){printf("就绪队列里的进程信息为:\");queWalk(&readyQueHead);}#define EndBlockTime 3 // 进程最长被阻塞时间int blockQueNum; // 阻塞队列的进程数量PCB blockQueHead; // 阻塞队列的头部PCB *blockMaxProcess; // 阻塞队列中优先级最高的进程// 进程插入到阻塞队列void blockQuePush(PCB *process){blockQueNum ++;process->blockTime = 0;process->state = Block;if (process->blockTime != -1) {QuePush(process, &blockQueHead);}}// 优先级最高的进程出列PCB* blockQuePop(){blockQueNum --;quePop(blockMaxProcess, &blockQueHead);return blockMaxProcess;}// 每个时间片,更新阻塞队列里进程的信息void blockQueUpdate(){int maxPriority = -1;PCB *pro = blockQueHead.nxt;while (pro != NULL){pro->blockTime ++;if (pro->blockTime >= EndBlockTime) {PCB *process = pro;pro = pro->nxt;// 阻塞时间到,调入就绪队列blockQueNum --;quePop(process, &blockQueHead); readyQuePush(process);} else if (pro->priority > maxPriority) {// 更新阻塞队列里优先级最高的进程指针maxPriority = pro->priority; blockMaxProcess = pro;pro = pro->nxt;}}}// 查看阻塞队列里进程的信息void blockQueWalk(){printf("阻塞队列里的进程信息为:\"); queWalk(&blockQueHead);}// 初始化数据void initData(){// 初始化就绪队列和阻塞队列readyQueNum = blockQueNum = 0; readyMaxProcess = blockMaxProcess = NULL;readyQueHead.pre = readyQueHead.nxt = NULL; blockQueHead.pre = blockQueHead.nxt = NULL; // 初始化进程进入就绪队列int i, maxPriority = -1;for (i = 0; i < N; i ++){// 分配一个PCB的内存空间PCB *pro = (PCB *)malloc(sizeof(PCB));// 给当前的PCB赋值pro->id = id[i];pro->priority = priority[i];pro->cpuTime = cpuTime[i];pro->allTime = allTime[i];pro->blockTime = blockTime[i];pro->startBlock = startBlock[i];if (pro->allTime > 0) {// 插入到就绪队列中readyQuePush(pro);// 更新就绪队列优先级最高的进程指针if (pro->priority > maxPriority) {maxPriority = pro->priority; readyMaxProcess = pro;}}}}// 模拟cpu执行1个时间片的操作void cpuWord(PCB *cpuProcess){cpuProcess->priority -= 3;if (cpuProcess->priority < 0) {cpuProcess->priority = 0;}cpuProcess->cpuTime ++;cpuProcess->allTime --;// 显示正执行进程的信息:printf("CPU正执行的进程信息为:\");printf("id: %d, pri: %d, alltime: %d\", cpuProcess->id,cpuProcess->priority, cpuProcess->allTime);}int main(){int timeSlice = 0; // 模拟时间片int cpuBusy = 0; // 模拟cpu状态PCB *cpuProcess = NULL; // 当前在cpu执行的进程initData(); // 初始化// 模拟进程调度while (1){if (readyQueNum == 0 && blockQueNum == 0 && cpuBusy == 0) { // 就绪队列、阻塞队列和cpu无进程,退出break;}if (cpuBusy == 0) {// cpu空闲,选择一个进程进入cpuif (readyQueNum > 0) {// 选择绪队列优先级最高的进程cpuProcess = readyQuePop();} else {// 就绪队列没有进程,改为选择阻塞队列优先级最高的进程cpuProcess = blockQuePop();}cpuProcess->cpuTime = 0;cpuProcess->state = Run;cpuBusy = 1;cpuProcess->startBlock --;}timeSlice ++;printf("\第%d个时间片后:\", timeSlice);// 模拟cpu执行1个时间片的操作cpuWord(cpuProcess);if (cpuProcess->allTime == 0) {cpuProcess->state = Finish;// 释放已完成进程的PCBfree(cpuProcess);cpuBusy = 0;}// 更新就绪队列和阻塞队列里的进程信息blockQueUpdate();readyQueUpdate();// 查看就绪队列和阻塞队列的进程信息readyQueWalk();blockQueWalk();if ((cpuProcess -> startBlock) > 0) {blockQuePush(cpuProcess);cpuProcess = readyQuePop();}else {if (cpuBusy == 1 && readyQueNum > 0 && cpuProcess->priority < readyMaxPriority()){readyQuePush(cpuProcess);cpuProcess = readyQuePop();}}}printf("\模拟进程调度算法结束2145115 刘成路\");return 0;}【运行截图】实验2使用动态分区分配方式的模拟1、实验目的(1)了解动态分区分配方式中使用的数据结构和分配算法(2)加深对动态分区存储管理方式及其实现过程的理解。
操作系统实验指导书梁海英编系部:班级:学号:姓名:淮安信息职业技术学院2009年1月5日实验须知1、实验前,应认真阅读实验指导书,明确实验目的和实验内容,做好实验准备。
2、实验中,积极思考,及时记录,有疑问及时解决,当堂完成实验内容和实验报告。
3、严格遵守实验实管理规则,珍惜实验时间,不做与实验无关的事。
4、实验结束,按要求填写实验机器使用记录单,正确关闭实验用机,整理好键盘和椅子,值日生认真打扫实验室卫生。
5、如实认真填写实验报告相关内容。
目录前言 (1)实验一 (3)实验二 (12)实验三 (21)实验四 (26)实验五 (33)实验六 (37)实验七 (43)实验一进程管理与控制实验日期:实验成绩:一、实验目的进程管理是操作系统多用户与多任务管理的基本重要手段,用户作业与任务进入内存后采用进程模式进行管理,利用不同进程对资源的不同要求实现进程的并发管理是提高系统效率的有效途径。
本实验的目的是要求学生通过实验全面了解进程管理与控制的相关内容,并通过Windows 2000系统中管理控制工具了解常见系统进程,分析系统性能。
二、实验指导与内容任务管理器是Windows系统中一个非常实用的系统工具,它提供了有关计算机性能的信息,并显示了计算机上所运行的程序和进程的详细信息,可以显示最常用的度量进程性能的单位;如果连接到网络,那么还可以查看网络状态并迅速了解网络是如何工作的。
启动任务管理器最常见的方法是同时按下“Ctrl+Alt+Del”组合键,还可以右键单击任务栏的空白处,然后单击选择“任务管理器”命令,或者,按下“Ctrl+Shift+Esc”组合键也可以打开任务管理器,当然,也可以为\Windows\System32\taskmgr.exe文件在桌面上建立一个快捷方式,然后为此快捷方式设置一个热键,以后就可以一键打开任务管理器了。
任务管理器的用户界面提供了文件、选项、查看、窗口、关机、帮助等六大菜单项,其下还有应用程序、进程、性能、联网、用户等五个标签页,窗口底部则是状态栏,从这里可以查看到当前系统的进程数、CPU使用比率、更改的内存、容量等数据,默认设置下系统每隔两秒钟对数据进行1次自动更新,当然你也可以点击“查看→更新速度”菜单重新设置。
目录实验一Windows 2000进程观测 (1)实验二Windows 2000进程控制 (3)实验三Windows 2000线程同步 (6)实验四Windows 2000线程间通信 (10)实验五Windows 2000内存结构 (14)《操作系统实验指导书》实验一Windows 2000进程观测一、实验目的:通过对Windows 2000编程,进一步熟悉操作系统的基本概念,较好地理解Windows 2000的结构。
二、实验环境:PC机、Windows 2000、V isual C++ 6.0专业版或企业版三、实验描述:对Windows 2000进程,利用任务程序观测四、实验要求:1.认真阅读和掌握本实验的算法。
2.上机将本算法实现。
3.保存和打印出程序的运行结果,并结合程序进行分析。
五、实验步骤:1. 简单的控制台应用程序我们先来创建一个名为“Hello,World”的应用程序。
步骤1:登录进入Windows 2000 Professional。
步骤2:在“开始”菜单中单击“程序”-“附件”-“记事本”命令,将清单1-l中的程序键入记事本中,并把代码保存为Hello.cpp。
清单1-1 一个简单的Windows 2000控制台应用程序// hello项目# include <iostream>void main(){std::cout << “Hello, Windows 2000” << std :: endl ;}步骤3:在“开始”菜单中单击“程序”-“附件”-“命令提示符”命令,进入Windows“命令提示符”窗口,并利用简单的标准命令行:C:\> CL Hello.cpp来创建可执行的Hello.EXE。
步骤4:运行Hello.EXE程序,产生用户键入的一行文字。
2. GUI应用程序在下面的实验中,C++ 编译器创建一个GUI应用程序,代码中包括了WinMain() 方法,这是GUI类型的应用程序的标准入口点。
操作系统实验指导书一、实验说明1、实验目的实验是操作系统原理课程中不可缺少的重要教学环节,实验目的是使学生理论联系实际,使学生在实践探索中去发现问题、去解决问题,提高了学生获取知识和应用技术的能力,培养了学生分析和解决问题的能力。
《操作系统原理》要求理论与实践相结合,本门实验课程是对《操作系统原理》课堂教学的一个重要补充,与理论学习起着相辅相成的作用,是实施《操作系统原理》教学的一个重要组成部分。
通过本实验课的实践学习,可以增强本专业的学生对系统实现的认识。
对加深理解和掌握操作系统相关原理有重要帮助。
2、实验要求进一步了解和掌握操作系统原理,提高系统设计的能力。
对每一实验题目,应独立完成,并要求:·上机前,学生必须做好充分的实验准备工作,掌握与实验相关的背景知识,用任一种高级语言编写程序。
·上机时,认真调试,并观察、记录程序运行过程中出现的现象和问题。
·上机后,分析实验结果并写出实验报告。
3、实验报告要求每个实验(包括选做的)均应编写实验报告,学生实验后要写出严谨的、实事求是的、文字通顺的、字迹公整的实验报告。
实验报告应包括以下内容:(1)实验题目(2)实验目的(3)实验内容●程序中使用的数据结构及符号说明●流程图●源程序清单并附上注释(4)实验结果及分析●运行结果(必须是上面程序清单所对应输出的结果)●对运行情况所作的分析以及本次调试程序所取得的经验。
如果程序未能通过,应分析其原因。
二、实验内容实验一熟悉使用计算机系统一、实验名称:熟悉使用计算机系统二、实验目的与要求通过对Windows操作系统的使用,熟悉Windows操作系统中的基本概念,如单用户、多任务、进程和文件等,熟悉Windows中命令行方式下常用命令的使用方法;进一步熟悉TC语言与开发环境,为以后的实验打好基础。
三、实验内容1.开机后,熟悉Windows的界面(桌面、任务栏、开始按钮<点击后出现“开始”菜单>、我的电脑图标、回收站、我的文档)。
作系统授课班级:11计本,11网工授课教师:梁宝华目录实验一进程管理 2 实验二存储器管理 9 实验三设备管理 16 实验四文件管理 21 实验五课程设计 27实验一进程管理//以下程序中有些错误,请找出并调试#include <stdio.h>#define TRUE 1#define FALSE 0#define MAXPRI 100#define NIL -1//进程控制块struct {int id; //进程号char status; //进程状态,'e'-执行态'r'-高就绪态't'-低就绪态'w'-等待态'c'-完成态int nextwr; //等待链指针,指示在同一信号量上等待的下一个等待进程的进程号。
int priority; //进程优先数,值越小,优先级越高。
int c;//进程中断次数}pcb[3];//共3个进程//s1、s2为三个进程共享的变量;seed为随机值;registeri模拟寄存器值,存放计算的重复次数。
int registeri,s1,s2,seed,exe=NIL;//exe为当前运行(占有cpu)的进程号//2个信号量sem[0]、sem[1],分别与共享变量s1、s2相联系。
//对应信号量sem[0]、sem[1]分别有两个阻塞队列,队列首由sem[].firstwr指定,队列链指针是pcb[].nextwrstruct{int value;//信号量值int firstwr;//等待该信号量的阻塞队列的首个进程号}sem[2];//三个进程的现场保留区,其中savearea[][0]为寄存器内容,savearea[][1]为下一条指令地址。
char savearea[3][4];char addr;//当前执行程序的当前指针void main();void init();float random();int timeint(char ad);int scheduler();int find();int p(int se,char ad);void block(int se);int v(int se,char ad);void wakeup(int se);void process1();void process2();void process3();void eexit(int n);//--------------------------------------------------------------------//主程序void main(){int currentProcess;printf("进程管理器\n");init();printf("s1=%d,s2=%d\n",s1,s2);printf("进程1、进程2、进程3已经准备好!\n");for (;;){currentProcess=scheduler(); //进程调度,选择优先级别最高的就绪进程运行。
if (currentProcess==NIL)break; //所有进程已经运行完毕,结束。
switch (currentProcess) //运行当前进程代码{case 0:break;case 1:process2();break;case 2:process3();break;default:printf("进程号出错!\n");break;}}printf("最后结果:s1=%d,s2=%d\n",s1,s2);}//------------------------------------------------------------------------ //初始化void init(){int i,j;s1=0;s2=0;//生成进程控制块for (j=0;j<3;j++){pcb[j].id=j; //进程号pcb[j].status='r'; //进程初始状态为高就绪状态pcb[j].nextwr=NIL;printf("\n进程%d 的优先数?",j+1);scanf("%d",&i);pcb[j].priority=i; //进程优先级pcb[j].c=0;}//初始化两个信号量sem[0].value=1;//与s1相联系sem[0].firstwr=NIL;sem[1].value=1;//与s2相联系sem[1].firstwr=NIL;//初始化现场保留区。
每个进程均有现场保留区。
for (i=1;i<3;i++)for (j=0;j<4;j++)savearea[i][j]='0';} //end of init()//生成0~1之间随机值float random(){int m;if (seed<0) m=-seed;else m=seed;seed=(25173*seed+13849)%65536;return (m/32767.0);}//----------------------------------------------------------------------------------//检测当前进程的时间片是否已到。
未到,返回FALSE,否则返回TRUE。
系统采用分时执行,//规定每个进程的执行概率为33%,用产生数x模拟时间片。
//ad为程序的当前语句地址。
int timeint(char ad){float x;x=random();if ((x<0.33)&&(exe==0)) return (FALSE);//当前进程为进程1,时间片未到。
if ((x>=0.33)&&(x<0.66)&&(exe==1)) return (FALSE);//当前进程为进程2,时间片未到。
if ((x>=0.66)&&(x<1)&&(exe==2)) return (FALSE);//当前进程为进程3,时间片未到。
//时间片已到处理:置正在执行进程状态为低就绪,处理器空闲。
savearea[exe][0]=registeri;//保存通用寄存器内容savearea[exe][1]=ad;//保存程序指针pcb[exe].status='t';//状态改为低就绪态printf("时间片中断,进程%d转入就绪态\n",exe+1);exe=NIL;return (TRUE);}//-----------------------------------------------------------------------------------//进程调度:选择一个进程投入运行。
返回当前进程的进程号。
int scheduler(){int pd;//选择投入运行的进程pdif ((pd=find())==NIL && exe==NIL)return (NIL);//无进程可运行,将结束。
if (pd!=NIL){if (exe==NIL) //选中了进程且处理器空闲,则投入运行。
{pcb[pd].status='e';exe=pd;printf("进程%d正在执行\n",exe+1);}else if (pcb[pd].priority<pcb[exe].priority)//选中进程的优选级别高于当前进程{//将当前进程转入高就绪状态pcb[exe].status='r';printf("进程%d进入就绪状态\n",exe+1);//选中进程pd投入执行pcb[pd].status='e';exe=pd;printf("进程%d正在执行\n",exe+1);}}//恢复进程现场registeri=savearea[exe][0];//恢复当前进程的寄存器。
addr=savearea[exe][1];//恢复执行进程的程序指针//修改优先权if(pcb[pd].c==3){pcb[pd].c=0;pcb[pd].priority=0;printf("\n!!进程%d中断次数达到3,优先级提高\n",pd+1);}return (exe);//返回当前进程的进程号}//---------------------------------------------------------------------------------//在3个进程中按就绪状态及其优先数选出进程。
返回选出的进程号。
int find(){int j,pd=NIL,w=MAXPRI;for (j=0;j<3;j++) //选择高就绪状态优先级最高的进程{if ((pcb[j].status=='r') && (pcb[j].priority<w)){w=pcb[j].priority;pd=j;}}if (pd==NIL) //没有高就绪状态的进程,寻找低就绪状态的进程。
{for (j=0;j<3;j++){if ((pcb[j].status=='t') && (pcb[j].priority<w)){w=pcb[j].priority;}}}return (pd);}//--------------------------------------------------------------------------------------//P操作,申请资源。
若申请se号资源成功,返回FALSE,若失败,把当前进程挂入se号资源的阻塞队列,//让出cpu,返回TRUE.//se为资源号,ad为程序当前指令的地址。
int p(int se,char ad){if (--sem[se].value>=0)return (FALSE);//资源申请成功//资源申请失败处理:block(se);//把当前进程挂入se号资源的阻塞队列savearea[exe][0]=registeri;//保存当前进程的寄存器内容savearea[exe][1]=ad;//保存当前进程的下一条指令地址exe=NIL;//让出CPUreturn (TRUE);//资源申请失败}//----------------------------------------------------------------------------//把当前进程阻塞,并挂到资源se的阻塞队列。