操作系统实验一模拟进程状态转换
- 格式:docx
- 大小:679.42 KB
- 文档页数:10
实验一进程调度实验一、目的要求用高级语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解。
二、例题:设计一个有 N个进程共行的进程调度程序进程调度算法:采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。
每个进程有一个进程控制块(PCB)表示。
进程控制块可以包含如下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。
进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。
进程的到达时间为进程输入的时间。
进程的运行时间以时间片为单位进行计算。
每个进程的状态可以是就绪 W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。
就绪进程获得CPU后都只能运行一个时间片。
用已占用CPU时间加1来表示。
如果运行一个时间片后,进程的已占用 CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。
每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。
重复以上过程,直到所要进程都完成为止。
调度算法的流程图如下图所示。
三.实验题:1、编写并调试一个模拟的进程调度程序,采用“最高优先数优先”调度算法对五个进程进行调度。
“最高优先数优先”调度算法的基本思想是把CPU分配给就绪队列中优先数最高的进程。
静态优先数是在创建进程时确定的,并在整个进程运行期间不再改变。
动态优先数是指进程的优先数在创建进程时可以给定一个初始值,并且可以按一定原则修改优先数。
例如:在进程获得一次CPU后就将其优先数减少1。
或者,进程等待的时间超过某一时限时增加其优先数的值,等等。
2、编写并调试一个模拟的进程调度程序,采用“轮转法”调度算法对五个进程进行调度。
轮转法可以是简单轮转法、可变时间片轮转法,或多队列轮转法。
实验一、进程调度实验报告一、实验目的进程调度是操作系统中的核心功能之一,其目的是合理地分配 CPU 资源给各个进程,以提高系统的整体性能和资源利用率。
通过本次实验,我们旨在深入理解进程调度的原理和算法,掌握进程状态的转换,观察不同调度策略对系统性能的影响,并通过实际编程实现来提高我们的编程能力和对操作系统概念的理解。
二、实验环境本次实验使用的操作系统为 Windows 10,编程语言为 C++,开发工具为 Visual Studio 2019。
三、实验原理1、进程状态进程在其生命周期中会经历不同的状态,包括就绪态、运行态和阻塞态。
就绪态表示进程已经准备好执行,只等待 CPU 分配;运行态表示进程正在 CPU 上执行;阻塞态表示进程由于等待某个事件(如 I/O操作完成)而暂时无法执行。
2、调度算法常见的进程调度算法有先来先服务(FCFS)、短作业优先(SJF)、时间片轮转(RR)等。
先来先服务算法按照进程到达的先后顺序进行调度。
短作业优先算法优先调度执行时间短的进程。
时间片轮转算法将 CPU 时间划分成固定大小的时间片,每个进程轮流获得一个时间片执行。
四、实验内容1、设计并实现一个简单的进程调度模拟器定义进程结构体,包含进程 ID、到达时间、执行时间、剩余时间等信息。
实现进程的创建、插入、删除等操作。
实现不同的调度算法。
2、对不同调度算法进行性能测试生成一组具有不同到达时间和执行时间的进程。
分别采用先来先服务、短作业优先和时间片轮转算法进行调度。
记录每个算法下的平均周转时间、平均等待时间等性能指标。
五、实验步骤1、进程结构体的定义```c++struct Process {int pid;int arrivalTime;int executionTime;int remainingTime;int finishTime;int waitingTime;int turnaroundTime;};```2、进程创建函数```c++void createProcess(Process processes, int& numProcesses, int pid, int arrivalTime, int executionTime) {processesnumProcessespid = pid;processesnumProcessesarrivalTime = arrivalTime;processesnumProcessesexecutionTime = executionTime;processesnumProcessesremainingTime = executionTime;numProcesses++;}```3、先来先服务调度算法实现```c++void fcfsScheduling(Process processes, int numProcesses) {int currentTime = 0;for (int i = 0; i < numProcesses; i++){if (currentTime < processesiarrivalTime) {currentTime = processesiarrivalTime;}processesistartTime = currentTime;currentTime += processesiexecutionTime;processesifinishTime = currentTime;processesiwaitingTime = processesistartTime processesiarrivalTime;processesiturnaroundTime = processesifinishTime processesiarrivalTime;}}```4、短作业优先调度算法实现```c++void sjfScheduling(Process processes, int numProcesses) {int currentTime = 0;int minExecutionTime, selectedProcess;bool found;while (true) {found = false;minExecutionTime = INT_MAX;selectedProcess =-1;for (int i = 0; i < numProcesses; i++){if (processesiarrivalTime <= currentTime &&processesiremainingTime < minExecutionTime &&processesiremainingTime > 0) {found = true;minExecutionTime = processesiremainingTime;selectedProcess = i;}}if (!found) {break;}processesselectedProcessstartTime = currentTime;currentTime += processesselectedProcessremainingTime;processesselectedProcessfinishTime = currentTime;processesselectedProcesswaitingTime =processesselectedProcessstartTime processesselectedProcessarrivalTime;processesselectedProcessturnaroundTime =processesselectedProcessfinishTime processesselectedProcessarrivalTime;processesselectedProcessremainingTime = 0;}}```5、时间片轮转调度算法实现```c++void rrScheduling(Process processes, int numProcesses, int timeSlice) {int currentTime = 0;Queue<int> readyQueue;for (int i = 0; i < numProcesses; i++){readyQueueenqueue(i);}while (!readyQueueisEmpty()){int currentProcess = readyQueuedequeue();if (processescurrentProcessarrivalTime > currentTime) {currentTime = processescurrentProcessarrivalTime;}if (processescurrentProcessremainingTime <= timeSlice) {currentTime += processescurrentProcessremainingTime;processescurrentProcessfinishTime = currentTime;processescurrentProcesswaitingTime =processescurrentProcessstartTime processescurrentProcessarrivalTime;processescurrentProcessturnaroundTime =processescurrentProcessfinishTime processescurrentProcessarrivalTime;processescurrentProcessremainingTime = 0;} else {currentTime += timeSlice;processescurrentProcessremainingTime = timeSlice;readyQueueenqueue(currentProcess);}}}```6、性能指标计算函数```c++void calculatePerformanceMetrics(Process processes, int numProcesses, double& averageWaitingTime, double& averageTurnaroundTime) {double totalWaitingTime = 0, totalTurnaroundTime = 0;for (int i = 0; i < numProcesses; i++){totalWaitingTime += processesiwaitingTime;totalTurnaroundTime += processesiturnaroundTime;}averageWaitingTime = totalWaitingTime / numProcesses; averageTurnaroundTime = totalTurnaroundTime / numProcesses;}```7、主函数```c++int main(){Process processes100;int numProcesses = 0;//创建进程createProcess(processes, numProcesses, 1, 0, 5);createProcess(processes, numProcesses, 2, 1, 3);createProcess(processes, numProcesses, 3, 2, 4);createProcess(processes, numProcesses, 4, 3, 2);//先来先服务调度fcfsScheduling(processes, numProcesses);double fcfsAverageWaitingTime, fcfsAverageTurnaroundTime;calculatePerformanceMetrics(processes, numProcesses, fcfsAverageWaitingTime, fcfsAverageTurnaroundTime);cout <<"先来先服务调度的平均等待时间:"<<fcfsAverageWaitingTime << endl;cout <<"先来先服务调度的平均周转时间:"<<fcfsAverageTurnaroundTime << endl;//短作业优先调度sjfScheduling(processes, numProcesses);double sjfAverageWaitingTime, sjfAverageTurnaroundTime;calculatePerformanceMetrics(processes, numProcesses, sjfAverageWaitingTime, sjfAverageTurnaroundTime);cout <<"短作业优先调度的平均等待时间:"<<sjfAverageWaitingTime << endl;cout <<"短作业优先调度的平均周转时间:"<<sjfAverageTurnaroundTime << endl;//时间片轮转调度(时间片为 2)rrScheduling(processes, numProcesses, 2);double rrAverageWaitingTime, rrAverageTurnaroundTime;calculatePerformanceMetrics(processes, numProcesses, rrAverageWaitingTime, rrAverageTurnaroundTime);cout <<"时间片轮转调度(时间片为 2)的平均等待时间:"<< rrAverageWaitingTime << endl;cout <<"时间片轮转调度(时间片为 2)的平均周转时间:"<< rrAverageTurnaroundTime << endl;return 0;}```六、实验结果与分析1、先来先服务调度平均等待时间:40平均周转时间:85分析:先来先服务调度算法简单直观,但对于短作业可能会造成较长的等待时间,导致平均等待时间和平均周转时间较长。
操作系统实验一模拟进程状态转换四、运行结果:图1 创建2个进程,因为这时cpu空闲所以内核调度,b优先级高先执行图2 超时,因为这时cpu空闲所以内核调度,b优先级还是比a高所以先执行图3 2个进程均被阻塞,其中一旦进程被阻塞就会引发调度图4 唤醒1个进程,从阻塞队列取队首放到就绪队列队尾,由于这时cpu空闲所以内核调度五、源代码:#include<cstdio>#include<algorithm>using namespace std;int Ready_len=0;int Blocked_len=0;int CPU_state=0;struct PCB{char name;int priority;int needtime;bool operator < (const PCB &b) const{return priority>b.priority;}};PCB Ready[100];PCB Blocked[100];PCB Cpu;bool dispatch();bool creat(int NUM){//创建一个新的进程while(NUM--){printf("输入进程名(一个字符)、所需时间(一个整数)、优先级(一个整数): \n");scanf("%s%d%d",&(Ready[Ready_len].name),&(Ready[Ready_len ].needtime),&(Ready[Ready_len].priority));getchar();Ready_len++;}if(CPU_state==0)//如果CPU空闲,则调度dispatch();}bool dispatch(){if(CPU_state==0){if(Ready_len!=0){sort(Ready,Ready+Ready_len);=Ready[0].name;Cpu.needtime=Ready[0].needtime;Cpu .priority=Ready[0].priority;if(Ready_len!=1)//就绪队列剔除队首元素for(int indx=1;indx<Ready_len;indx++){Ready[indx-1].name=Ready[indx].name;Ready[indx-1].needtime= Ready[indx].needtime;Ready[indx-1].priority=Ready[indx].priority;}Ready_len--;CPU_state=1;printf("***%c进程送往CPU执行\n",);Cpu.needtime--;Cpu.priority--;}else{printf("***就绪队列为空,无法调度\n");return false;}}else{printf("***CPU忙,无法调度\n");}}bool time_out(){if(CPU_state==1){if(Cpu.needtime==0)printf("***%c时间片用完,并且执行完毕,被释放\n",);else{Ready[Ready_len].name=;Ready[Ready_len].needtime= Cpu.needtime;Ready[Ready_len].priority=Cpu.priority;Ready_len++;printf("***%c时间片用完\n",);}CPU_state=0;=0;Cpu.needtime=0;Cpu.priority=0;if(Ready_len!=0)//时间片用完,如果就绪队列不为空,则调度dispatch();}else{printf("***没有进程在CPU中,无法超时\n");}}bool event_wait(){if(CPU_state==1){Blocked[Blocked_len].name=;Blocked[Blocked_len].n eedtime=Cpu.needtime;Blocked[Blocked_len].priority=Cpu.priority;Blocked_len++;printf("***%c被阻塞\n",);CPU_state=0;if(Ready_len!=0)//进程被阻塞,如果就绪队列不为空,则调度dispatch();}elseprintf("***没有进程在CPU中,无法阻塞\n");}bool event_occur(){if(Blocked_len!=0){//sort(Blocked,Blocked+Blocked_len);Ready[Ready_len].name=Blocked[0].name;Ready[Ready_len].nee dtime=Blocked[0].needtime;Ready[Ready_len].priority=Blocked[0]. priority;Ready_len++;if(Blocked_len!=1)//阻塞队列剔除队首元素for(int indx=1;indx<Blocked_len;indx++){Blocked[indx-1].name=Blocked[indx].name;Blocked[indx-1].needti me=Blocked[indx].needtime;Blocked[indx-1].priority=Blocked[indx]. priority;}Blocked_len--;//printf("%d %d",Blocked_len,Ready_len);printf("***%c被唤醒\n",Ready[Ready_len-1].name);if(CPU_state==0)//如果CPU空闲,则调度dispatch();//printf("%d %d",Blocked_len,Ready_len);}elseprintf("***阻塞队列为空,无法唤醒\n");}int main(){int Cputime=1;while(1){printf("\n1:New\t\t\t2:Dispatch\n");printf("3:Timeout\t\t4:Event wait\n");printf("5:Event occur\t\t0:exit\n");printf("输入1--5实现相应的功能:\n");int select;scanf("%d",&select);getchar();switch(select){case 1:int num;printf("输入要创建的进程数:\n");scanf("%d",&num);getchar();creat(num);break;case 2:dispatch();break;case 3:time_out();break;case 4:event_wait();break;case 5:event_occur();break;case 0:exit(0);break;}printf("****************************Cputime:%3d********************* *******\n",Cputime);printf("状态\t\t进程名\t\t需要时间\t\t优先级\n");if(CPU_state){//显示CPU中的进程printf("Running:\t%c\t\t",);printf("%d\t\t\t",Cpu.needtime);printf("%d\n",Cpu.priority);}if(Ready_len){//显示Ready队列中的进程for(int a=0;a<Ready_len;a++){printf("Ready%d:\t\t",a);printf("%c\t\t",Ready[a].name);printf("%d\t\t\t",Ready[a].needtime);printf("%d\n",Ready[a].priority);}}if(Blocked_len){//显示Blocked队列中的程序for(int b=0;b<Blocked_len;b++){printf("Blocked%d:\t",b);printf("%c\t\t",Blocked[b].name);printf("%d\t\t\t",Blocked[b].needtime);printf("%d\n",Blocked[b].priority);}}printf("**************************************************************** ***\n");Cputime++;} }。
实验进程状态转换及其PCB的变化、程序流程图:、使用的数据结构及说明:在本实验中,主要用到的数据结构是PCB的结构,其中PCB的数据结构如下: struct PCB {int P_ld;char P_Name[10];char P_State[10];int P_Ru ntime;int P_Requiry; struct PCB * n ext ;l -//PCB 的ID 号//PCB的名称//PCB状态//PCB的所需要的运行时间//PCB所需要的资源要求//PCB块的下一个指针其中,P_Id,和P_Name 用来标示一个进程,而P_State用来标示进程的五种状态:Create_state,Ready_state,Block_state,Run_state,Exit_state 。
P_Runtime 标示要完成一个进程所需 要的时间。
P_Requiry 标示一个进程的执行所需要的其他条件, 当其他的条件满足, 则 P_Requiry 置1,否则置0。
Struct PCB * next 用来指向同一队列中的下一个PCB 块。
三、程序源代码 :#include"stdlib.h" #include"stdio.h" #include"string.h"/********** globle structure and viable ******/ struct PCB//PCB 的 ID 号//PCB 的名称//PCB 状态//PCB 的所需要的运行时间 //PCB 所需要的资源要求 //PCB 块的下一个指针{ p=*head; q=p->next;p=q;q=q->next;}// 将节点插入队列{int P_Id;char P_Name[10]; char P_State[10]; int P_Runtime; int P_Requiry; struct PCB * next ; } ;struct PCB * Create_state; struct PCB * Run_state; struct PCB * Ready_state; struct PCB * Block_state; struct PCB * Exit_state; int signal4=0; int signal5=0;// 创建状态 // 运行状态 // 就绪状态 // 阻塞状态// 退出状态 // 标示进程 // 标示进程的完成状态 的完成状态void InsertQueue(struct PCB **head,struct PCB *node){struct PCB * p,*q; node->next=NULL; if(*head==NULL){*head=node;}Else/* insert node function */// 如果队列为空// 队列不空while(q!=NULL) {// 找到最后的元素位置p->next=node;void DeleteQueue(struct PCB **head,struct PCB *node) {struct PCB *p,*q; q=*head;if(node->P_Requiry)printf("this process resource is ready \n");elseprintf("this process resource is not ready ! \n");}void DispatchToBlock(struct PCB *node) // /* dispatch to block function*/ { // 调度到阻塞状态的函数//struct PCB *p=(struct PCB *)malloc(sizeof(struct PCB));if(!node->P_Requiry) // 如果所需要的资源没有满足则,调度到阻塞状态 { strcpy(node->P_State,"block");InsertQueue(&Block_state,node); // 插入到阻塞队列 Display_Process(node);if(*head==NULL||node==NULL) return ; if(*head==node) { *head=(*head)->next; return; } Else { while(q->next!=p&&q->next!=NULL)q=q->next; q=p->next; p->next=NULL;}} void Display_Process(struct PCB * node) {printf("\n\nthis process Id is printf("this process name is printf("this process state is printf("this process Runtime is // 如果队列为空,返回 // 如果要删除的元素是队首元素// 如果不是队列的首元素// 打印进程状态的元素函数 : %d \n",node->P_Id); : %s \n",node->P_Name); : on %s \n ",node->P_State); : %d \n",node->P_Runtime);// 撤销进程,从队列中删除元素void DispatchToReady(struct PCB *node) // dispatch to ready state{ // 调度到就绪状态的函数 if(node->P_Requiry) // 如果所需的资源满足,则调度{strcpy(node->P_State,"Ready");InsertQueue(&Ready_state,node); Display_Process(node);}}void DispatchBlockToReady() //dispatch the process to readyqueueInsertQueue(&Ready_state,p);printf("process4 will be in the state of ready!\n"); Display_Process(p);} if(signal5&&p->P_Id==5){DeleteQueue(&Block_state,p); strcpy(p->P_State,"ready");InsertQueue(&Ready_state,p);printf("process5 will be in the state of ready!\n"); Display_Process(p);} } }void Create_Process(){int i;struct PCB *p; char name[10];{ struct PCB*p,*q;q=Block_state; while(q!=NULL){p=q; q=q->next;if(signal4&&p->P_Id==4){DeleteQueue(&Block_state,p); strcpy(p->P_State,"ready");// 从阻塞状态调度到就绪状态函数 // 如果阻塞状态队列不空//如果所需要的资源满足// 创建进程函数strcpy(name,"process"); // 动态创建 2 个处于阻塞状态的进程p=(struct PCB *)malloc(sizeof(struct PCB)); p->P_Id=i; name[7]=i+'0';name[8]='\0'; strcpy(p->P_Name,name); strcpy(p->P_State,"create");p->P_Runtime=1; // 所需要的时间片为 1 p->P_Requiry=0; Display_Process(p); sleep(4);printf(" \n process%d will be in the state of Block, waiting the resource ready \n\n",i); DispatchToBlock(p); // 同时调度到阻塞队列// 创建 4 个就绪状态的队列p=(struct PCB *)malloc(sizeof(struct PCB)); p->P_Id=i; name[7]=i+'0'; name[8]='\0';strcpy(p->P_Name,name); strcpy(p->P_State,"create"); p->P_Requiry=1; p->P_Runtime=2; elsep->P_Runtime=1; Display_Process(p); sleep(4);printf(" \n process%d will be in the state of Ready, waiting to run \n\n",i); DispatchToReady(p);void display(struct PCB **head) {struct PCB *p,*q; p=*head;for(i=1;i<3;i++){for(i=3;i<7;i++){if(i==6)// 在这里个进程 6while(p!=NULL) { sleep(2);//printf("\n\n///////////////////////////////////\n"); printf("\n\nthis process Id is printf("this process name is printf("this process state is printf("this process Runtime is if(p->P_Requiry)printf("this process resource is ready \n");elseprintf("this process resource is not ready ! \n"); p=p->next;} }{printf("this process is not finished,will be dispatch to the ready queue!!\n"); DeleteQueue(&Ready_state,p);strcpy(p->P_State,"ready"); InsertQueue(&Ready_state,p);Display_Process(p);}Else // 执行完成,则跳出,并发送相应的信息 {printf("\n\nProcess%d is finished and will be in the state of exit!\n\n",p->P_Id);if(p->P_Id==4) signal4=1; if(p->P_Id==5) signal5=1; } if(signal4||signal5)DispatchBlockToReady(); // 如果资源满足,则将进程调度到就绪队列 q=q->next;p=q;}if(q==NULL) printf("\nthere is no process ready!\n STOP Machine!!!\n");}int main(int argc,char * argv[]) // 主函数: %d \n",p->P_Id); : %s \n",p->P_Name); : on %s \n ",p->P_State); : %d \n",p->P_Runtime);void Process_Run(){struct PCB *p,*q; p=Ready_state; q=p;while(p!=NULL){if(p->P_Runtime<=0) break; strcpy(p->P_State,"running"); Display_Process(p);p->P_Runtime=p->P_Runtime-1; sleep(4);if(p->P_Runtime>0)// 进程运行函数// 就绪队列不空则继续执行 // 如果时间片执行完了,则跳出循环// 没有完成,则进入就绪队列{int i;char c='c'; // 界面printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ \n"); printf(" Ding Hai bo\n");printf(" ..... P ress s to start the process ...... \n");scanf("%c",&c);while(1){if(c=='s')break; scanf("%c",&c);}Create_Process(); // 调用创建进程函数printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); printf("\n>>>>>>> Display the Ready queue >>>>>>>>>>>>>>>\n"); sleep(5);display(&Ready_state); //////////////// 显示就绪队列里的进程printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");printf("\n>>>>>>>> Display the Block queue >>>>>>>>>>>>\n");sleep(5); // 显示阻塞队列函数display(&Block_state); /////////////////////printf("\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n\n");printf("\n>>>>>>>> Now the process start to run >>>>>>>>>>>\n");sleep(5);Process_Run(); // 调用进程运行函数}四、运行结果及说明:运行结果的截图:下面的运行结果是程序执行的每一步进程调度的显示,从进程的创建到进程的执行,结束,每一步进程调度都有显示。
一、实验背景及目的进程是操作系统中基本的活动单位,进程管理是操作系统核心功能之一。
为了深入理解进程的概念、进程状态转换、进程同步与互斥等知识,我们进行了进程管理实验。
本次实验旨在通过编写程序,模拟进程的创建、调度、同步与互斥等操作,加深对进程管理的理解。
二、实验内容及方法1. 进程创建与状态转换(1)使用系统调用fork()创建子进程,观察父进程和子进程的状态转换过程。
(2)使用系统调用exec()替换子进程的内容,观察子进程状态变化。
2. 进程调度(1)编写进程调度程序,实现最高优先数优先调度算法和先来先服务调度算法。
(2)模拟进程就绪队列,观察调度算法对进程执行顺序的影响。
3. 进程同步与互斥(1)使用信号量实现进程同步,观察进程同步效果。
(2)使用互斥锁实现进程互斥,观察进程互斥效果。
4. 进程通信(1)使用管道实现进程间通信,观察通信效果。
(2)使用共享内存实现进程间通信,观察通信效果。
三、实验结果与分析1. 进程创建与状态转换实验结果显示,使用fork()创建子进程后,父进程和子进程的状态均为运行态。
当父进程调用exec()替换子进程内容后,子进程状态变为僵尸态,父进程状态变为运行态。
这说明进程在创建和替换过程中,其状态发生了相应的变化。
2. 进程调度实验结果显示,最高优先数优先调度算法和先来先服务调度算法均能正确执行。
最高优先数优先调度算法下,优先级高的进程先执行;先来先服务调度算法下,先到达的进程先执行。
这说明两种调度算法均能实现进程的合理调度。
3. 进程同步与互斥实验结果显示,使用信号量实现进程同步时,进程能正确地按照规定的顺序执行;使用互斥锁实现进程互斥时,进程能正确地实现互斥访问共享资源。
这说明信号量和互斥锁在进程同步与互斥方面具有重要作用。
4. 进程通信实验结果显示,使用管道实现进程间通信时,进程能正确地接收和发送数据;使用共享内存实现进程间通信时,进程能正确地访问共享内存中的数据。
操作系统-进程的状态与转换进程的状态与转换状态进程是程序的⼀次执⾏。
在这个执⾏过程中,有时进程正在被CPU处理,有时⼜需要等待CPU服务,可见,进程的状态是会有各种变化。
为了⽅便对各个进程的管理,操作系统需要将进程合理地划分为⼏种状态。
三种基本状态运⾏态(Running)CPU√ 其他所需资源×占有CPU,并在CPU上运⾏注意:单核处理机环境下,每⼀时刻最多只有⼀个进程处于运⾏态。
(双核环境下可以同时有两个进程处于运⾏态)。
就绪态(Ready)CPU√ 其他所需资源×已经具备运⾏条件,但由于没有空闲CPU,⽽暂时不能运⾏进程已经拥有了除了处理机之外所有需要地资源,⼀旦获得处理机,即可⽴即进⼊运⾏态开始运⾏。
即:万事俱备,只⽋CPU。
阻塞态(Waiting/Blocked,⼜称等待态)CPU× 其他所需资源×因等待某⼀事件⽽暂时不能运⾏如:等待操作系统分配打印机,等待读磁盘操作地结果。
CPU是计算机中最昂贵地部件,为了提⾼CPU地利⽤率,需要先将其他进程需要地资源分配到位,才能得到CPU的服务。
另外两种状态创建态(New,⼜名:新建态)进程正在被创建,操作系统为进程分配资源、初始化PCB。
终⽌态(Terminated,⼜称:结束态)进程正在从系统中撤销,操作系统会回收进程拥有的资源。
进程状态的转换图⽚来⾃王道考研B站视频截图就绪态=>运⾏态进程被调度运⾏态=>就绪态时间⽚到,或CPU被其他⾼优先级的进程抢占运⾏态=>阻塞态等待系统资源分配,或等待某事件发⽣(主动⾏为)阻塞态=>就绪态资源分配到位,等待事件的发⽣(被动⾏为)⼏个注意点运⾏态=>阻塞态是⼀种进程⾃⾝作出的主动⾏为阻塞态=>就绪态不是进程⾃⾝能控制的,是⼀种被动⾏为不能由阻塞态直接转换为运⾏态,也不能由就绪态直接转换为阻塞态(因为进⼊阻塞态是进程主动请求的,必然需要进程在运⾏时才能发出这种请求)。
操作系统进程管理实验报告一、引言在现代计算机科学中,操作系统的进程管理是确保系统高效运行的关键环节。
本实验旨在通过观察和分析操作系统的进程管理行为,深入理解进程的创建、运行和终止过程,以及操作系统如何对进程进行调度和资源分配。
二、实验目标1、理解进程的基本概念、进程状态及转换。
2、掌握进程的创建、终止和调度方法。
3、观察和分析进程在运行过程中的资源消耗和调度行为。
4、分析操作系统对进程的资源分配和调度策略对系统性能的影响。
三、实验环境与工具本实验在Linux操作系统上进行,使用GNU/Linux环境下的工具进行进程的创建、监控和调度。
四、实验步骤与记录1、创建进程:使用shell命令“fork”创建一个新的进程。
记录下父进程和子进程的PID,以及它们在内存中的状态。
2、进程状态观察:使用“ps”命令查看当前运行进程的状态,包括进程的PID、运行时间、CPU使用率等。
同时,使用“top”命令实时监控系统的CPU、内存等资源的使用情况。
3、进程调度:在“crontab”中设置定时任务,观察系统如何根据预设的调度策略分配CPU资源给各个进程。
4、资源分配:通过修改进程的优先级(使用“nice”命令),观察系统如何调整资源分配策略。
5、终止进程:使用“kill”命令终止一个进程,并观察系统如何处理该进程占用的资源。
五、实验结果与分析1、创建进程:通过“fork”系统调用,成功创建了一个新的进程,并获取了父进程和子进程的PID。
在内存中,父进程和子进程的状态分别为“running”和“ready”。
2、进程状态观察:使用“ps”命令可以看到父进程和子进程的状态均为“running”,同时显示了它们的CPU使用率和运行时间等信息。
通过“top”命令,可以实时监控系统的CPU、内存等资源的使用情况,为进一步分析提供了数据支持。
3、进程调度:在“crontab”中设置定时任务后,系统会根据预设的调度策略以及各个进程的运行状态,动态地分配CPU资源给各个进程。
一、实验目的1. 理解进程的概念和进程状态转换。
2. 掌握进程同步与互斥的基本方法。
3. 学习使用信号量实现进程同步与互斥。
4. 熟悉进程调度算法。
二、实验环境1. 操作系统:Windows/Linux2. 编程语言:C/C++3. 开发工具:Visual Studio/Code::Blocks三、实验内容1. 进程状态转换2. 进程同步与互斥3. 信号量实现进程同步与互斥4. 进程调度算法四、实验步骤1. 进程状态转换```c#include <stdio.h>#include <unistd.h>void print_status(int state) {switch (state) {case 1: printf("创建状态\n"); break; case 2: printf("就绪状态\n"); break;case 3: printf("运行状态\n"); break; case 4: printf("阻塞状态\n"); break; case 5: printf("终止状态\n"); break; default: printf("未知状态\n"); break; }}int main() {int state = 1;print_status(state);sleep(1);state = 2;print_status(state);sleep(1);state = 3;print_status(state);sleep(1);state = 4;print_status(state);sleep(1);state = 5;print_status(state);return 0;}```2. 进程同步与互斥```c#include <stdio.h>#include <pthread.h>pthread_mutex_t lock;void thread_func(void arg) {pthread_mutex_lock(&lock);printf("线程 %d 进入临界区\n", (int )arg);sleep(2);printf("线程 %d 离开临界区\n", (int )arg);pthread_mutex_unlock(&lock);return NULL;}int main() {pthread_t tid1, tid2;int arg1 = 1, arg2 = 2;pthread_mutex_init(&lock, NULL);pthread_create(&tid1, NULL, thread_func, &arg1); pthread_create(&tid2, NULL, thread_func, &arg2); pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_mutex_destroy(&lock);return 0;}```3. 信号量实现进程同步与互斥```c#include <stdio.h>#include <pthread.h>#include <semaphore.h>sem_t sem;void thread_func(void arg) {sem_wait(&sem);printf("线程 %d 进入临界区\n", (int )arg);sleep(2);printf("线程 %d 离开临界区\n", (int )arg);sem_post(&sem);return NULL;}int main() {pthread_t tid1, tid2;int arg1 = 1, arg2 = 2;sem_init(&sem, 0, 1);pthread_create(&tid1, NULL, thread_func, &arg1); pthread_create(&tid2, NULL, thread_func, &arg2);pthread_join(tid1, NULL);pthread_join(tid2, NULL);sem_destroy(&sem);return 0;}```4. 进程调度算法```c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define MAX_PROCESSES 5typedef struct {int pid;int arrival_time;int burst_time;int wait_time;int turnaround_time;} Process;int compare(const void a, const void b) {Process proc1 = (Process )a;Process proc2 = (Process )b;return proc1->arrival_time - proc2->arrival_time;}void fcfs(Process processes[], int n) {processes[0].wait_time = 0;processes[0].turnaround_time = processes[0].burst_time;for (int i = 1; i < n; i++) {processes[i].wait_time = processes[i - 1].turnaround_time + processes[i].arrival_time - processes[i].burst_time;processes[i].turnaround_time = processes[i].wait_time + processes[i].burst_time;}}int main() {Process processes[MAX_PROCESSES] = {{1, 0, 3, 0, 0},{2, 1, 6, 0, 0},{3, 4, 4, 0, 0},{4, 6, 5, 0, 0},{5, 8, 2, 0, 0}};qsort(processes, MAX_PROCESSES, sizeof(Process), compare);fcfs(processes, MAX_PROCESSES);for (int i = 0; i < MAX_PROCESSES; i++) {printf("PID: %d, Wait Time: %d, Turnaround Time: %d\n", processes[i].pid, processes[i].wait_time, processes[i].turnaround_time);}return 0;}```五、实验结果与分析通过以上实验,我们了解了进程状态转换、进程同步与互斥、信号量实现进程同步与互斥以及进程调度算法。
3.2.4 被挂起的进程交换的需要前面描述的三个基本状态(就绪态、运行态和阻塞态)提供了一种为进程行为建立模型的系统方法,并指导操作系统的实现。
许多实际的操作系统都是按照这样的三种状态进行具体构造的。
但是,可以证明往模型中增加其他状态也是合理的。
为了说明加入新状态的好处,考虑一个没有使用虚拟内存的系统,每个被执行的进程必须完全载入内存,因此,图3.8b 中,所有队列中的所有进程必须驻留在内存中。
所有这些设计机制的原因都是由于I/O 活动比计算速度慢很多,因此在单道程序系统中的处理器在大多数时候是空闲的。
但是图3.8b 的方案并没有完全解决这个问题。
在这种情况下,内存保存有多个进程,当一个进程正在等待时,处理器可以转移到另一个进程,但是处理器比I/O 要快得多,以至于内存中所有的进程都在等待I/O 的情况很常见。
因此,即使是多道程序设计,大多数时候处理器仍然可能处于空闲状态。
一种解决方法是内存可以被扩充以适应更多的进程,但是这种方法有两个缺陷。
首先是内存的价格问题,当内存大小增加到兆位及千兆位时,价格也会随之增加;再者,程序对内存空间需求的增长速度比内存价格下降的速度快。
因此,更大的内存往往导致更大的进程,而不是更多的进程。
另一种解决方案是交换,包括把内存中某个进程的一部分或全部移到磁盘中。
当内存中没有处于就绪状态的进程时,操作系统就把被阻塞的进程换出到磁盘中的“挂起队列”(suspendqueue),这是暂时保存从内存中被“驱逐”出的进程队列,或者说是被挂起的进程队列。
操作系统在此之后取出挂起队列中的另一个进程,或者接受一个新进程的请求,将其纳入内存运行。
“交换”(swapping)是一个I/O 操作,因而也可能使问题更加恶化。
但是由于磁盘I/O 一般是系统中最快的I/O(相对于磁带或打印机I/O),所以交换通常会提高性能。
为使用前面描述的交换,在我们的进程行为模型(见图3.9a)中必须增加另一个状态:挂起态。
实验一模拟进程状态转换及其PCB的变化一、实验目的:
自行编制模拟程序,通过形象化的状态显示,使学生理解进程的概念、进程之间的状态转换及其所带来的PCB内容、组织的变化,理解进程与其PCB间的一一对应关系。
二、实验内容及要求:
(1)、设计并实现一个模拟进程状态转换及其相应PCB内容、组织结构变化的程序。
(2)、独立编写、调试程序。
进程的数目、进程的状态模型(三状态、五状态、七状态或其它)以及PCB的组织形式可自行选择。
(3)、合理设计与进程PCB相对应的数据结构。
PCB的内容要涵盖进程的基本信息、控制信息、资源需求及现场信息。
(4)、设计出可视性较好的界面,应能反映出进程状态的变化引起的对应PCB内容、组织结构的变化。
(5)、代码书写要规范,要适当地加入注释。
(6)、鼓励在实验中加入新的观点或想法,并加以实现。
(7)、认真进行预习,完成预习报告。
(8)、实验完成后,要认真总结,完成实验报告。
三、实现:
数据结构
struct PCB{
char name;
int priority;
int needtime;
bool operator < (const PCB &b) const{ return priority>;
}
};
五状态进程模型
最高优先数优先调度算法流程图
四、运行结果:
图1 创建2个进程,因为这时cpu空闲所以内核调度,b优先级高先执行
图2 超时,因为这时cpu空闲所以内核调度,b优先级还是比a高所以先执行
图3 2个进程均被阻塞,其中一旦进程被阻塞就会引发调度
图4 唤醒1个进程,从阻塞队列取队首放到就绪队列队尾,由于这时cpu空闲所以内核调
度
五、源代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int Ready_len=0;
int Blocked_len=0;
int CPU_state=0;
struct PCB{
char name;
int priority;
int needtime;
bool operator < (const PCB &b) const{
return priority>;
}
};
PCB Ready[100];
PCB Blocked[100];
PCB Cpu;
bool dispatch();
bool creat(int NUM){ame),&(Ready[Ready_len].needtime),&(Ready[Ready_len].prior ity));getchar();
Ready_len++;
}
if(CPU_state==0)ame;=Ready[0].needtime;=Ready[0].priority;
if(Ready_len!=1)ame=Ready[indx].name;Ready[indx-1].needtime=Ready[indx].needtime;Ready[indx-
1].priority=Ready[indx].priority;
}
Ready_len--;
CPU_state=1;
printf("***%c进程送往CPU执行\n",;
;
;
}else{
printf("***就绪队列为空,无法调度\n");
return false;
}
}else{
printf("***CPU忙,无法调度\n");
}
}
bool time_out(){
if(CPU_state==1){
if==0)
printf("***%c时间片用完,并且执行完毕,被释放\n",;
else{
Ready[Ready_len].name=;Ready[Ready_len].needtime=;Ready[Ready _len].priority=;
Ready_len++;
printf("***%c时间片用完\n",;
}
CPU_state=0;
=0;
=0;
=0;
if(Ready_len!=0)ame=;Blocked[Blocked_len].needtime=;Blocked[Bloc ked_len].priority=;
Blocked_len++;
printf("***%c被阻塞\n",;
CPU_state=0;
if(Ready_len!=0)ame=Blocked[0].name;Ready[Ready_len].needtime=
Blocked[0].needtime;Ready[Ready_len].priority=Blocked[0].priority;
Ready_len++;
if(Blocked_len!=1)ame=Blocked[indx].name;Blocked[indx-1].needtime=Blocked[indx].needtime;Blocked[indx-
1].priority=Blocked[indx].priority;
}
Blocked_len--;
ame);
if(CPU_state==0)ame);
printf("%d\t\t\t",Ready[a].needtime);
printf("%d\n",Ready[a].priority);
}
}
if(Blocked_len){ame);
printf("%d\t\t\t",Blocked[b].needtime);
printf("%d\n",Blocked[b].priority);
}
}
printf("************************************************************* ******\n");
Cputime++;
} }。