精华内容
下载资源
问答
  • 在多道程序或任务系统中,系统回时处于就绪态的进程有若干个,为使系统中 进程能有条不素地运行,必须选择某种调度策略,以选择一进程占用处理机。 要求学生设计一个模拟单处理机调度算法,以巩固和加探对进念...

    操作系统算法模拟实例之单处理机系统进程调度

    1.实验目的

    在多道程序或多任务系统中,系统回时处于就绪态的进程有若干个,为使系统中
    的各进程能有条不素地运行,必须选择某种调度策略,以选择一进程占用处理机。
    要求学生设计一个模拟单处理机调度算法,以巩固和加探对进念和进程调度算法的理解。

    2.实验内容

    编写程序完成单处理机系统中的进程调度,要求采用最高优先级优先调度算法。具体内容包括

    • 确定进程控制块的内容和组织方式;
    • 完成进程创建原语和进调度原语:
    • 编写主函数井对所做的工作进行测试

    3.实验指导

    进程调度算法:

    采用最高优先级优先调度算法(即把处理机分配给优先级最高的进程)和先来先服务调度算法,每个进程用一个进程控制块(PCB)表示,进程控制块可以包含以下信息:进程名、优先数、到达时间、需要运行时间、已用CPU时间,进程状态等。进程的优先数(表示优先级别)及需要的运行时间可以事先人为描定(也可以随机数产生),进程的到达时间为进程输入的时间。进程的运行时间以时间片为单位。

    每个进程的状态可以是就绪W(Wait),运行R(Run)或完成F( Finish)三种状态之就绪进程获得CPU后都只能运行一个时间片,用已占用CPU时间加1来表示,如果运行一个时间片后,进程的已占用CPU时间已达到所需要的运行时间,则激销该进程,如果运行一个时间片后进程的已占用CPU时间还未达到所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。

    每进行一次,调度程序都打印一次运行进程,就绪队列以及各个进程的PCB,以假进
    行检查。重复以上过程,直到所有进程都完成为止。

    4.程序实例

    #include"stdio.h"
    #include <stdlib.h>
    #include <conio.h>
    #define getpch(type)(type *)malloc(sizeof(type))
    
    struct pcb               //定义进程控制块
    {
        char name[10];
        char state;
        int super;
        int ntime;
        int rtime;
        struct pcb* link;
    }*ready=NULL,*p;
    typedef struct pcb PCB;
    int sort()                  //建立对进程进行优先级排列的函数
    {
        PCB *first,*second;
        int insert = 0;
        //优先级最大者,插入队首
        if((ready==NULL)||((p->super )>(ready->super )))
        {
            p->link =ready;
            ready=p;
        }
        else        //进程比较优先级,插入适当的位置中
        {
            first = ready;
            second = first->link ;
            while(second != NULL)
            { //插入进程比当前进程优先数大、插到当前进程前面
                if((p->super )>(second->super ))
                {
                    p->link =second;
                    first->link = p ;
                    second = NULL;
                    insert = 1;
                }
                else    //插入进程优先级数最低,则插入到队尾
                {
                    first=first->link ;
                    second=second->link ;
                }
            }
            if(insert==0)   first->link=p;
        }
    }
    /*
        说明:上述程序首先定义进程控制块结构,然后对每个进程的优先级赋初值,完成
        优先级的排序过程,把优先级大的进程插入就绪队首,等待cup调度,该实验完成了
        优先级大者优先调度的原则,从而对进程调度过程加深理解和掌握
    */
    int input() //建立进程控制块函数
    {
        int i,num;
    
        system("cls");       //清屏
        printf("\n请输入进程个数?");
        scanf("%d",&num);
        for(i = 0; i < num; i++)
        {
            printf("\n进程号 No.%d:\n",i);
            p = getpch(PCB);
            printf("\n输入进程名:");
            scanf("%s",p->name );
            printf("\n 输入进程优先数:");
            scanf("%d",&p->super );
            printf("\n 输入进程运行时间:");
            scanf("%d",&p->ntime );
            printf("\n");
            p->rtime = 0;
            p->state = 'w';
            p->link = NULL;
            sort();
        }
    }
    int space()
    {
        int l = 0;
        PCB *pr = ready;
        while(pr!=NULL)
        {
            l++;
            pr = pr->link;
    
        }
        return(l);
    }
    int disp(PCB *pr)
    {
        printf("\n qname\t state\t super \t ndtime \t runtime \n");
        printf("|%s\t",pr->name);
        printf("|%c\t",pr->state);
        printf("|%d\t",pr->super);
        printf("|%d\t",pr->ntime);
        printf("|%d\t",pr->rtime);
        printf("\n");
    
    }
    int check()         //进程查看函数
    {
        PCB *pr;
        printf("\n****当前正在运行的程序是:%s",p->name );     //显示当前运行进程
        disp(p);
        pr=ready;
        printf("\n****当前就绪队列状态为:\n");                //显示就绪队列状态
        while (pr!=NULL)
        {
            disp(pr);
            pr=pr->link;
        }
    }
    int destroy()                      //建立进程撤销函数(进程运行结束,撤销进程)
    {
        printf("\n进程{%s}已完成.\n",p->name );
        free(p);
    
    }
    int running()                  //建立进程就绪函数(进程运行时间到,置就绪状态)
    {
        (p->rtime )++;
        if(p->rtime ==p->ntime )
            destroy();
        else
        {
            (p->super )--;
            p->state ='w';
            sort();
        }
    }
    int main()
    {
        int len,h = 0;
        char ch;
        input();
        len = space();
        while((len!=0)&&(ready != NULL))
        {
            ch=getchar();
            h++;
            printf("\n The execute number:%d\n",h);
            p=ready;
            ready=p->link ;
            p->link =NULL;
            p->state ='R';
            check();
            running();
            printf("\n 按任意键继续....");
            ch=getchar();
    
        }
        printf("\n\n进程已经完成.\n");
        ch=getchar();
    }
    
    展开全文
  • 1. 处理机调度概念 ...处理机调度就是从就绪队列挑选下一个占用CPU运行的进程单处理机),如果是多处理机的话,就还包含从个可以用的CPU挑选就绪进程可使用的CPU资源。 调度程序是指内核当中,用...

    1. 处理机调度概念

    处理机调度是操作系统当中用来管理处理机执行能力的这一部分资源的功能。

    1. CPU资源的时分复用
      之前进程切换实际上就是对CPU资源的当前占用者的一种切换,通过这种切换来实现CPU资源的时分复用。

      处理机调度就是从就绪队列中挑选下一个占用CPU运行的进程(单处理机),如果是多处理机的话,就还包含从多个可以用的CPU中挑选就绪进程可使用的CPU资源。
      调度程序是指在内核当中,用来挑选就绪进程的函数。 这里面就包含两个问题,一是调度策略(依据什么原则挑选进程/线程),二是调度时机

    2. 调度时机
      ==1==


    2. 调度准则

    1. 调度策略
      ==2==

    2. 处理机资源的使用模式
      进程通常是在CPU计算和I/O操作间交替运行
      ==3==

    3. 比较调度算法好坏的准则

      CPU使用率:CPU处于忙状态的时间百分比
      吞吐量:单位时间内完成的进程数量(这前两个都是基于系统效率来讲,后面的是从用户的角度)
      周转时间:进程从初始化到结束(包括等待)的总时间
      等待时间:进程在就绪队列中的总时间
      响应时间:从提交请求到产生响应所花费的时间(对于交互性应用)

      ==7==


    1. 吞吐量与相应时间的关系
      ==4==
    2. 处理机调度策略的目标
      1. 响应时间目标(响应时间是操作系统的计算延迟)
        ==5==
      2. 吞吐量目标(吞吐量是操作系统的计算带宽)
        ==6==
      3. 公平性目标
        公平的定义:保证每个进程占用相同的CPU时间或者保证每个进程的等待时间相同。公平通常会增加平均响应时间。

    3. 调度算法

    前三种为关于就绪队列排序的算法,主要是根据先后达到顺序、执行时间、等待时间来排序。
    ==8==

    1. 先来先服务算法(FCFS)

    ==9==
    ==10==
    在上图中,进程进入等待或者结束状态就意味着进程主动让出CPU,周转时间指的是进程进程从初始化到结束(包括等待)的总时间。

    2. 短进程优先算法(SPN)

    由于先来先服务算法周转时间抖动的问题,将进程的执行时间也考虑到算法里。短进程优先算法的策略就是选择就绪队列中执行时间最短进程占用CPU进入运行状态。这种算法具有最优平均周转时间
    ==11==

    1. 缺点
      ==12==
    2. 改进:短剩余时间优先算法(SRT):如果A进程的剩余执行时间短于当前正在执行的进程的剩余时间,则允许CPU资源被A进程抢占。

    3. 最高响应比优先算法(HRRN)

    在短进程优先算法中,会因为长进程等的时间而出现而出现饥饿问题。就出现了这种算法

    在这里插入图片描述


    4. 时间片轮转算法(RR)

    在该算法中,首先约定一个进程调度的基本时间单位:时间片,它是处理机进行资源分配的基本单位。其基本思路就是按照各个进程按照时间片轮流的占用CPU资源。

    1. 工作原理
      ==14==
    2. 示例
      ==15==
    3. 时间片的长度选择问题
      ==16==

    在前面的算法中,每个进程占用CPU多长时间定下来了,排队的先后顺序也定下来了。但是这仍然无法满足应用程序的所有要求。所以为了综合前面的算法,就出现了下面的几种算法。

    5. 多级队列调度算法(MQ)

    基本思路

    1. 就绪队列被划分为多个独立的子队列,比如说前台需要交互,那么可以用时间轮转算法(时间片设置短些),后台主要是批处理,就可以用先来先服务。
    2. 各个队列拥有自己的调度策略
    3. 队列间的调度采用下图的策略

    ==17==

    6. 多级反馈队列算法(MLFQ)

    在多级队列调度算法中,各个队列之间是没有交互的,也就是进程不能在队列间移动,这就出现了该算法。注意,下图中的高优先级对应的是第1级;
    ==18==
    算法特征: CPU密集型进程的优先级会下降很快(这样也就相当于执行时间越长的进程,切换的频率就会越低,开销越小)。I/O密集型的进程会停留在高优先级(因为每次算的时间都很短,时间片没用完)

    7. 公平共享算法(FFS)

    ==19==
    ==20==


    4. 实时调度+多处理器调度

    实时调度是对时间有要求的调度算法,多处理器调度是指在有多个处理器的系统里的调度算法

    1. 实时调度

    1. 实时操作系统
      时间约束的可预测性就是说在什么情况下,时间约束是可以达到的。
      ==21==

    2. 实时任务以及周期实时任务
      ==22==
      ==23==
      ==24==

    3. 可调度性
      在下图的示例中,系统在执行这三个周期实时任务时是可调度的么?
      ==25==

    4. 实时调度的两种算法
      ==26==


    2. 优先级反置

    注意:在Unix和Linux系统中,优先级越高,值越小。在Windows中,优先级越高,值越大。这里采用第2种。
    基于优先级的可抢占调度算法会出现优先级反置。

    1. T1优先级为40,它正在运行状态中,占用资源L1
    2. 然后,另一个进程T2(优先级为50)进入运行状态,在T2的运行过程中,需要申请T1已占用的资源L1,此时,由于T1已经占用了资源L1,所以T2就处于等待状态。
    3. 假设这时T3抢占CPU进入运行状态,而T1被迫停止了(且资源也没有释放),那么T2就会一直等待T1的资源,就产生了优先反置现象。
      ==29==
    1. 优先级继承
      下图中,在时刻t3,T3进入了阻塞。在时刻t4,占用资源的T3继承了申请资源T1的优先级,T3就会继续执行,释放资源后,T3的优先级就会变为原来的。
      ==30==
    2. 天花板协议
      ==31==

    3. 多处理器调度

    ==27==
    ==28==

    展开全文
  • 编写程序完成单处理机系统中的进程调度,要求采用时间片轮转调度算法。实验具体包括:首先确定进程控制块内容,进程控制块组成方式;然后完成进程创建原语和进程调度原语;最后编写主函数对所作工作进程测试。 ...
  • 编写程序完成单处理机系统中的进程调度,要求采用时间片轮转调度算法。实验具体包括:首先确定进程控制块内容,进程控制块组成方式;然后完成进程创建原语和进程调度原语;最后编写主函数对所作工作进程测试。 ...
  • 其中处理机管理功能:传统的多道程序系统中处理机的分配和运行都是以进程为基本单元的,因而对处理机管理可以归纳为对进程的管理。 处理机管理的主要功能有:创建和撤销进程,对诸进程的运行进行协调,实现进程...

    1.传统的OS中应具有处理机管理、存储器管理、设备管理和文件管理等基本功能。

    其中处理机管理功能:在传统的多道程序系统中,处理机的分配和运行都是以进程为基本单元的,因而对处理机管理可以归纳为对进程的管理。

    处理机管理的主要功能有:创建和撤销进程,对诸进程的运行进行协调,实现进程之间的信息交换,以及按照一定的算法将处理机分配给进程。

    在多道程序环境下为使作业能并发执行,必须为每道作业创建一个或多个进程,并为之分配必要的资源。当进程运行结束时,应立即撤销该进程,

    以便能及时回收所占用的各种资源,使其他进程进行使用。在设置有线程的OS中,进程控制还应包括为一个进程创建若干个线程,以提高系统的并发性。

    因此,进程控制的主要功能也就是为作业创建进程,撤销已结束的进程,以及控制进程在运行过程中的状态转换(进程基本状态的转换:就绪(Ready)状态、执行(Running)状态、阻

    塞(Block)状态等状态之间的转换)。

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    2.进程同步

    进程:所谓进程是指,在系统中能够独立运行并作为资源分配的基本单位,它是由一组机器指令、数据和堆栈等组成的,是一个独立运行的活动实体。多个进程之间可以并发执行和交换信息。
    为使多个进程能有条不紊地进行,系统中必须设置相应的进程同步机制。该机制的主要任务是为多个进程(含线程)的运行进行协调。
    常用的协调方式有两种:
    1)进程互斥方式,这是指诸进程在对临界资源进行访问时,应采用互斥方式;
    2)进程同步方式,指在相互合作去完成任务的诸进程间,由同步机构对他们的执行次序加以协调。
    最简单的用于实现进程互斥的机制是为每一个临界资源配置一把锁,当锁打开时,进程可以对该临界区资源进行访问,而锁关上时,
    则禁止进程访问该临界资源。而实现进程同步时,最常用的机制是信号量机制。

    展开全文
  • 本代码模拟在单处理机情况下处理机调度问题。 逐步求精法定义(摘自百度百科) 将现实问题经过几次抽象(细化)处理,最后到求解域只是一些简单算法描述和算法实现问题。即将系统功能按层次进行分解,每一层...

    操作系统进程调度在C++中的实现

    进程调度代码简介

    多道程序设计中,经常是若干个进程同时处于就绪状态,必须依照某种策略来决定那个进程优先占有处理机。因而引起进程调度。本代码模拟在单处理机情况下的处理机调度问题。

    逐步求精法的定义

    将现实问题经过几次抽象(细化)处理,最后到求解域中只是一些简单的算法描述和算法实现问题。即将系统功能按层次进行分解,每一层不断将功能细化,到最后一层都是功能单一、简单易实现的模块。求解过程可以划分为若干个阶段,在不同阶段采用不同的工具来描述问题。在每个阶段有不同的规则和标准,产生出不同阶段的文档资料。——百度百科

    这个方法特别感谢我的老师推荐给平常写代码比较少的我,对代码的实现和学习都有很大的帮助,同时也会大大减少代码报错的可能性,让排查错误也更加简单,也能提高自己写代码的自信,很推荐同样对代码不熟悉的朋友使用。

    代码实现

    头文件及宏定义

    #include<iostream>
    #include<string>
    #include<map>
    #include<time.h>
    using namespace std;
    #define random(x) rand()%(x)
    

    由于要使用字符串定义进程状态(就绪、执行、完成)、同时还需要兼顾用户使用的可观方便性,输入字符串(比如:Yes or No)会比输入数字(比如:1、2、3)更容易理解和操作,所以引入头文件string。
    我们还需使用map模板来实现进程的按优先级排序以及利用map自动按key升序排序,所以可以将key定义为优先级,这样可以简化甚至直接免除了我们排序的算法。
    对于逐步求精后代码功能逐渐完善,我们需要用到随机数给进程随机出需要运行时间和优先级,所以添加宏定义,方便后续代码随机数的使用,也提高代码的可读性。同时需要插入头文件time.h作为随机数种子,让随机数真正随机。

    准备&选择模块

    srand(time(NULL));//随机数种子,只需执行一次
    cout << "请输入进程数n(建议4~8个):" << endl;
    	int n;
    	cin >> n;
    	cout << "请选择调度方法:1.动态优先权法请输入Y或y 2.轮转法请输入N或n" << endl;
    	string cho;
    	cin >> cho;
    	int id;//进程编号
    	if (cho == "Y" || cho == "y"){
    		
    	}
    	else if (cho == "N" || cho == "n") {
    
    	}
    	else { cout << "您的输入有误!请输入Y / y或N / n" << endl; }
    }
    

    在实验中老师推荐进程数最好在4~8个之间,原因应该是能检测代码编写的正确性的同时可以高效地运行,所以我们这里用整型n定义进程数,并且输出一行语句提示用户输入合理范围的进程数。
    再定义字符串类型的变量cho(这里是choose的缩写,可以增强代码的可视性,直接定义成choose或者其他变量均可),提示用户输入Y/y或N/n来选择动态优先权法还是轮转法。
    注意,这里的两个输出语句一定要写在各自的输入语句的前面,要不然用户在操作界面需要先输入才能看到提示语句,显然这样与我们想要的功能不一致
    同时我们要考虑到代码的鲁棒性,由于字符串的特殊性,用户很可能输入错误,所以我们在if条件语句里就将用户输错可能性考虑上,在输入不为Y/y/N/n时给出输出提示。

    动态优先权法模块

    固定数值(逐步求精第一步)

    我们这边开始使用逐步求精法,先将代码最简单化,将所有动态数据全部静态化,用常量定义每个进程的优先级、需要运行时间,这样输出一组静态的数据,易于我们刚开始这个算法的实现,而后再逐步将常量都实现随机数化。

    int a[5] = { 0,2,2,2,2 };//第一个数值不用
    		multimap<int,int>processlist;
    		processlist.insert(pair<int, int>(1, 3));//1对应的是优先级、3对应的是进程编号
    		processlist.insert(pair<int, int>(3, 2));
    		processlist.insert(pair<int, int>(2, 1));
    		processlist.insert(pair<int, int>(4, 4));
    		while(processlist.empty()==false){
    			for (auto list = processlist.begin(); list != processlist.end(); list++)
    				cout << "进程编号" << list->second << "的进程优先级为" << list->first << ",状态为:就绪" << endl;
    			cout << "进程编号" << processlist.begin()->second << "的进程状态变为:进行" << endl;
    			a[processlist.begin()->second] -= 1;
    			if (a[processlist.begin()->second] == 0)
    			{
    				cout << "进程编号" << processlist.begin()->second << "的状态变为:完成" << endl;
    			}
    			else
    			{
    				processlist.insert(pair<int, int>((processlist.begin()->first) + 1, processlist.begin()->second));
    			}
    			processlist.erase(processlist.begin());
    }
    

    对于这个这个模块的代码一开始我也没有完善界面显示美观问题,这个也一并放入后面的逐步求精里面。
    首先解释一下这里用到的map模板:map是c++的一个标准容器,它提供了很好一对一的关系,所以在这里我们用进程编号与优先级一一对应非常好用,同时更好的是因为map会自动根据元素值排序,这样可以省掉我们的排序算法,map直接输出的就是按优先级排好的队列。(关于map函数的基本用法可以搜索“C++map”就可以搜到相关算法,难度不高,搜索相关教学视频也能更好地理解)
    首先我们定义一个数组来存放每个进程需要的运行时间,这里我们直接将进程数量默认为4,所以建立一个a[5]数组,至于为什么是5呢,因为这样放弃a[0]的值后,可以将a[1]、a[2]、a[3]、a[4]与进程1、2、3、4一一对应,更便于我们后续代码的编写。然后我们将每个程序的需要运行时间都设置为2,这个数值用来测试我个人觉得真的很好,因为2的话每个进程就需要调出两次,可以非常完美地检测是否能正常调入,如果设置为1,那就只有一次调出没有调入,而设置为3的话明显又显得重复繁琐,并不需要3次调出和2次调入来测试。(时间设置与调入/调出次数的关系如下表所示)按测试来说,只需调入调出各至少有一次即可。

    时间的设置 调入次数 调出次数
    1 0 1
    2 1 2
    3 2 3
    multimap<int,int>processlist;
    

    随后我们构造一个multimap,为什么这边要使用multimap,是因为在运行过程中优先级会变化,而普通map中元素值不能重复,如果重复就会出现直接丢失的情况,所以如果我们直接使用map,在优先级变为一样时的两个进程就有一个直接消失了。而multimap其实就是一个可以重复元素的map(注意这里的multi不要拼错)。processlist是我定义的这个map的名字,可以根据自己的需要随意更改,这边由于我们在做进程调度,所以简易地翻译成进程(process)列表(list)。
    继续,我们插入四个进程,第一个元素定义为优先级,第二个元素定义为进程编号,这样定义有什么好处呢:很简单,因为map的自动排序是按照第一个元素的大小数值的,所以将第一个元素定义为优先级可以直接发挥map的自动排序功能为我们排序进程队列,而输出进程编号和优先级数值时,可以轻松地交换位置,并不影响输出顺序。

    while(processlist.empty()==false)
    

    这个语句用来控制程序的循环结束,表达的意思就是一旦map里所有元素都删除了,相应的进程就都完成了。

    for (auto list = processlist.begin(); list != processlist.end(); list++)
    

    这句代码是遍历整个map,很好理解,processlist.begin()找到的就是第一个进程,相对的end就是最后一个。同时这边定义了局部变量list,主要也是为了遍历map,具体实现方法应该还有其他的,由于我也是现学的map,觉得这一种比较好理解。
    list->second一眼就能看出是指向第二个元素,比如pair<int,int>(1,3)里指向的就是这里的3,而list->first当然就是指向这里的1啦。
    到这里,我们就完成了整个进程队列的创建和展示,接下来就是实现进程调度了:

    cout << "进程编号" << processlist.begin()->second << "的进程状态变为:进行" << endl;
    

    这里一开始我还是想贯彻逐步求精,先将这里的processlist.begin()->second直接写成processlist.find(1),按道理来说静态的数值更直观,直接找到优先级为1的进程然后状态变为进行,但是我在编写的时候发现这样写有一个问题,优先级在继续深入运行的过程中,会变成2、3、4,如果每次根据具体数值变换的话,需要每运行一个循环就跑一遍代码输出看一下下一个优先级最高的是哪个进程,然后才能选取到将要进行的进程。所以我这里直接将processlist.find(1)定义为processlist.begin()->second,也非常易懂,还直接实现了每个循环中都可以使用这个代码,对于begin刚刚讲过就是map最前端的进程,而我们要选取的就是最前端的进程,而->second指向second是因为我们将第二个元素定义为了进程编号,千万不要指到first,要不然指向的是优先级,虽然能跑通,但界面就全乱了。

    a[processlist.begin()->second] -= 1;
    

    这边之前定义数组时将编号与数组一一对应的好处就体现出来了,直接用map里的编号赋值给数组,将对应进程的所需时间-1。

    if (a[processlist.begin()->second] == 0)
    			{
    				cout << "进程编号" << processlist.begin()->second << "的状态变为:完成" << endl;
    			}
    			else
    			{
    				processlist.insert(pair<int, int>((processlist.begin()->first) + 1, processlist.begin()->second));
    			}
    			processlist.erase(processlist.begin());
    

    随后就需要用一个if来判断,如果所需时间为0了,就不需要再进入进程队列了,直接输出这个进程完成了,如果还没为0,就将刚刚的优先级+1,编号不变的一个新元素插入map,然后再删除第一个元素。这里不在插入前删除,是因为优先级+1后的新元素一定排在刚刚运行过的进程的后面,所以可以放心先插入再删除,以便使用删除前的数值,而不需要再找变量来存储赋值。
    这里给一个跑代码的截图:
    在这里插入图片描述
    至此我们用常量完成了动态优先级算法模块,说是常量,其实大部分我们都已经实现了自动化,没有直接去抓取常量,接下来要做的就是将常量用随机数赋值就行了,由此可见用map来实现进程调度确实是个好选择呀!

    随机数变量(逐步求精第二步)

    接下来我稍微改动一下代码,用循环将原本的常量赋值为随机数,很快便将求精的代码跑通了:

    int a[10];
    		for (int num = 1; num <= n; num++) 
    		{
    			a[num] = random(4) + 1;
    		}
    		multimap<int,int>processlist;
    		for (int num = 1; num <= n; num++) 
    		{
    			processlist.insert(pair<int, int>(random(4)+1, num));
    		}
    		while(processlist.empty()==false){
    			for (auto list = processlist.begin(); list != processlist.end(); list++)
    				cout << "进程编号" << list->second << "的进程优先级为" << list->first << ",状态为:就绪" << endl;
    			cout << "进程编号" << processlist.begin()->second << "的进程状态变为:进行" << endl;
    			a[processlist.begin()->second] -= 1;
    			if (a[processlist.begin()->second] == 0)
    			{
    				cout << "进程编号" << processlist.begin()->second << "的状态变为:完成" << endl;
    			}
    			else
    			{
    				processlist.insert(pair<int, int>((processlist.begin()->first) + 1, processlist.begin()->second));
    			}
    			processlist.erase(processlist.begin());
    		}
    

    首先同样地定义一个整型数组存放各个进程所需运行时间,同样的因为要放弃a[0]所以根据进程数n的数量是4~8应该定为9,我这边又多给了一个余量,写了10,如果需要更多进程则可以定义更多。所需时间我定义在了一秒至四秒,这个也可以根据自己的需要定,不过最好不要太大否则会出现输出太多的情况。
    然后我们要做的就是把map中的编号用循环从1给到n,同时也给每个进程随机出了优先级,优先级我也定义为了1~4,这个也是不要定太大,要不然每个进程的优先级差别很大,很可能都没有顺序的变换,每次都是第一个进程执行到结束,然后再下一个进程。
    就这样我们很轻松就对上一步代码进行了求精,跑的结果我放两个在下面:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    第一张是跑4个进程,第2~4张是跑8个进程,可见8个进程的输出是成指数增加的,所以最好不要输入超过8个的进程。
    到这里,我们已经基本完成了动态优先级算法,接下来我们只需要对用户界面进行求精即可,这个阶段只要细致一些不缺少分号已经不会出错啦。

    完善用户/输出界面(逐步求精第三步)

    动态优先级算法放入完整代码中的效果:

    #include<iostream>
    #include<string>
    #include<map>
    using namespace std;
    #define random(x) rand()%(x)
    void main() 
    {
    	cout << "****************************************************************" << endl;
    	cout << "欢迎使用本程序~" << endl;
    	cout << "请输入进程数n(建议4~8个):" << endl;
    	int n;
    	cin >> n;
    	cout << "请选择调度方法:1.动态优先权法请输入Y或y 2.轮转法请输入N或n" << endl;
    	string cho;
    	cin >> cho;
    	int id;
    	if (cho == "Y" || cho == "y"){
    		int a[10];
    		for (int num = 1; num <= n; num++) 
    		{
    			a[num] = random(4) + 1;
    		}
    		multimap<int,int>processlist;
    		for (int num = 1; num <= n; num++) 
    		{
    			processlist.insert(pair<int, int>(random(4)+1, num));
    		}
    		while(processlist.empty()==false){
    			for (auto list = processlist.begin(); list != processlist.end(); list++)
    				cout << "进程编号" << list->second << "的进程优先级为" << list->first << ",状态为:就绪,剩余需要运行时间为"<<a[list->second] << endl;
    			cout << "进程编号" << processlist.begin()->second << "的进程状态变为:进行" << endl;
    			a[processlist.begin()->second] -= 1;
    			if (a[processlist.begin()->second] == 0)
    			{
    				cout << "进程编号" << processlist.begin()->second << "的状态变为:完成" << endl;
    			}
    			else
    			{
    				processlist.insert(pair<int, int>((processlist.begin()->first) + 1, processlist.begin()->second));
    			}
    			processlist.erase(processlist.begin());
    		}
    	}
    	else if (cho == "N" || cho == "n") {
    
    	}
    	else { cout << "您的输入有误!请输入Y / y或N / n" << endl; }
    	cout << "谢谢使用本程序!祝您生活愉快~" << endl;
    	cout << "****************************************************************" << endl;
    }
    

    在这里插入图片描述

    轮转法模块

    由于轮转法的实现相较于动态优先级算法更为简单,同时有了前面算法的铺垫,我就不逐句讲解了,将最终代码附上并加一个轮转法跑通的截图:

    #include<iostream>
    #include<string>
    #include<map>
    #include<time.h>
    using namespace std;
    #define random(x) rand()%(x)
    void main() 
    {
        srand(time(NULL));//随机数种子,只需执行一次
    	cout << "****************************************************************" << endl;
    	cout << "欢迎使用本程序~" << endl;
    	cout << "请输入进程数n(建议4~8个):" << endl;
    	int n;
    	cin >> n;
    	cout << "请选择调度方法:1.动态优先权法请输入Y或y 2.轮转法请输入N或n" << endl;
    	string cho;
    	cin >> cho;
    	int id;
    	if (cho == "Y" || cho == "y"){
    		int a[10];
    		for (int num = 1; num <= n; num++) 
    		{
    			a[num] = random(4) + 1;
    		}
    		multimap<int,int>processlist;
    		for (int num = 1; num <= n; num++) 
    		{
    			processlist.insert(pair<int, int>(random(4)+1, num));
    		}
    		while(processlist.empty()==false){
    			for (auto list = processlist.begin(); list != processlist.end(); list++)
    				cout << "进程编号" << list->second << "的进程优先级为" << list->first << ",状态为:就绪,剩余需要运行时间为"<<a[list->second] << endl;
    			cout << "进程编号" << processlist.begin()->second << "的进程状态变为:进行" << endl;
    			a[processlist.begin()->second] -= 1;
    			if (a[processlist.begin()->second] == 0)
    			{
    				cout << "进程编号" << processlist.begin()->second << "的状态变为:完成" << endl;
    			}
    			else
    			{
    				processlist.insert(pair<int, int>((processlist.begin()->first) + 1, processlist.begin()->second));
    			}
    			processlist.erase(processlist.begin());
    		}
    	}
    	else if (cho == "N" || cho == "n") {
    		int a[10];
    		for (int num = 1; num <= n; num++)
    		{
    			a[num] = random(4) + 1;
    		}
    		map<int, int>processlist;
    		for (int num = 1; num <= n; num++)
    		{
    			processlist.insert(pair<int, int>(num, num));
    		}
    		while (processlist.empty() == false) {
    			for (auto list = processlist.begin(); list != processlist.end(); list++)
    				cout << "进程编号" << list->second << "的进程优先级为" << list->first << ",状态为:就绪,剩余需要运行时间为" << a[list->second] << endl;
    			cout << "进程编号" << processlist.begin()->second << "的进程状态变为:进行" << endl;
    			a[processlist.begin()->second] -= 1;
    			if (a[processlist.begin()->second] == 0)
    			{
    				cout << "进程编号" << processlist.begin()->second << "的状态变为:完成" << endl;
    			}
    			else
    			{
    				processlist.insert(pair<int, int>((processlist.begin()->first) + n, processlist.begin()->second));
    			}
    			processlist.erase(processlist.begin());
    		}
    	}
    	else { cout << "您的输入有误!请输入Y / y或N / n" << endl; }
    	cout << "谢谢使用本程序!祝您生活愉快~" << endl;
    	cout << "****************************************************************" << endl;
    }
    

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    processlist.insert(pair<int, int>((processlist.begin()->first) + n, processlist.begin()->second));
    

    唯一要讲的就是这个思路,轮转法可见我直接用了map而不是multimap,那我为什么确定不会出现相同的优先级呢,是因为我的这一句代码(第66行),这个语句让每个进程输出后的优先级直接加n,这样能确保运行过的进程直接排到队尾,而且还不可能出现相同的优先级致使元素丢失。

    总结

    第一次写CSDN的博客,很多地方说的不好大家多多包涵,如果有更好的改进可以联系我一起探讨,感谢看到这里的读者,谢谢!

    展开全文
  • 文章目录Linux处理机管理1.进程1.1.进程的概念1.2.进程的定义1.3....Linux系统中,提高处理机使用率技术措施主要是道和分时,处理机在进程之间切换,按照一定规则轮流执行每个进程。对于单个处
  • 一个CPU计算机系统中,有两台外部设备R1、R2和三个进程P1、P2、P3。系统采用可剥夺式优先级的进程调度方案,且所有进程可以并行使用I/O设备,三个进程的优先级、使用设备先后顺序和占用设备时间如下表所示:...
  • 处于此状态的进程的数目小于等于处理器数目,对于单处理机系统,处于运行状态的进程只有一个。没有其他进程可以执行时(如所有进程阻塞状态),通常会自动执行系统的空闲进程。 (2)就绪:当
  • 本节书摘来自华章计算机《深入理解大数据:大数据处理与编程实践》一书中的第2章,第2.2节,作者 主 编:黄宜华(南京大学)副主编:苗凯翔(英特尔公司),更章节内容可以访问云栖社区“华章计算机”公众号查看。...
  • 在单处理机系统中,在一秒中内,可能1-15ms运行A程序,15-30运行B程序,以此类推,给人一种错觉是在同一时刻运行。 在处理机系统中,在一秒内,可能1-15ms在C1处理器运行A程序,也可能在1-15ms内在C2处理器运行B...
  • 理解并掌握处理机调度算法 二实验内容及要求 在采用系统的设计程序往往有若干进程同时处于就绪状态当就绪状态进程数 大于处理机数时就必须按照某种策略来决定哪些进程优先占用处理机本实验模拟在单处 ...
  • 进程的状态 就绪(Ready)状态 当进程已分配到除CPU以外所有必要资源后,只要再获得CPU,便可立即执行,...在单处理机系统中,只有一个进程处于执行状态; 在处理机系统中,则有进程处于执行状态。  
  • 处于此状态的进程的数目小于等于处理器数目,对于单处理机系统,处于运行状态的进程只有一个。没有其他进程可以执行时(如所有进程阻塞状态),通常会自动执行系统的空闲进程。 (2)就绪:当一个进程获得...
  • 分布式操作系统中进程同步

    千次阅读 2005-04-16 23:20:00
    在多机条件下,相互合作的进程可能不同的处理机上运行,进程间的通信涉及处理机的通信问题。松散耦合系统中进程间通信还可能要通过较长的通信信道,甚至网络。因此,在多机条件下,广泛采用间接通信方式,即...
  • 操作系统中的三级调度是指( ) A.处理机调度、资源调度和I/O调度 ...在单处理机的多进程系统中,进程切换时什么时候占用处理机和占用多长时间取决于( ) A.进程程序段的长度 B.进程需要运行的时...
  • 操作系统处理机管理

    千次阅读 2017-03-14 09:37:58
     在单道程序系统中,程序只能够顺序执行,即两个程序只能等一个执行完再执行下一个。这样就使程序执行具有三个特型:顺序性、封闭性和可再现性。而到了道程序系统中,允许程序并发执行(宏观并行,微观串行...
  • 进程则是在处理机一次执行过程,是一个动态概念。 进程:一个具有独立功能程序关于某个数据集一次运行活动,它是操作系统执行基本单元。 线程: 通常一个进程中可以包含若干个线程,至少有一个成为...
  • 操作系统原理 实验四 处理机调度

    千次阅读 2020-06-30 08:36:27
    本实验模拟在单处理器情况下处理器调度,帮助学生加深理解处理机调度算法。 2、实验预备内容 (1)C语言源程序调试和编译知识。 (2)掌握优先数调度算法和时间片轮转法原理。 3、实验内容 (1)设计一个按...
  • 进程的状态及转换一. 进程的状态及转换①. 进程的三态模型1. 执行(running)态2. 就绪(ready)态3....在单处理机系统中,只有一个进程处于执行状态; 在处理机系统中,则有进程处于执行状态。
  • 一、定义 进程:指在系统中能独立运行并作为资源分配基本单位,它是由一组机器指令、数据和堆栈等组成,是一个能独立运行活动实体。...处于此状态的进程的数目小于等于处理器数目,对于单处理机系统,处...
  • 在采用道程序设计的系统中,往往有若干个进程同时处于就绪状态。当就绪进程个数大于处理器数时,就必须依照某种策略来决定哪些进程优先占用处理器。本实习模拟在单处理器情况下处理器调度,帮助学生加深了解...
  • 操作系统进程线程

    2021-01-25 22:27:47
    计算机操作系统中把并行性和并发性明显区分开,主要是从微观的角度来说的,具体是指进程的并行性(处理机的情况下,进程同时运行)和并发性(单处理机的情况下,进程在同一时间间隔运行的)。 并发与并行...
  • 操作系统进程调度

    2018-01-20 14:37:45
    单处理机下,常见的进程调度算法包括:先来先服务(FIFO)算法,优先级调度算法和时间片轮转算法。 FIFO算法根据进程到达先后顺序进行调度。 优先级调度算法是从就绪队列选出优先级最高的进程,让它CPU上运行...
  • [进程]进程的状态转换

    千次阅读 2013-04-28 18:57:58
    在单处理机系统中,只有一个进程处于执行状态; 在处理机系统中,则有进程处于执行状态。 就绪(ready)态:进程具备运行条件,等待系统分配处理器以便运行状态。 当进程已分配到除CPU以外所有...
  • 在单处理器的多进程系统中,进程什么时候占有处理器以及决定占用时间的长短是由( B )决定的。 A、进程运行时间 B、进程的特点和进程调度策略 C、进程执行的代码 D、进程完成什么功能 时间片轮转算法是...
  • 本实验模拟在单处理机情况下处理机调度问题,加深对进程调度理解。操作系统管理了系统的有限资源,当有进程(或进程发出请求)要使用这些资源时,因为资源有限性,必须按照一定原则选择进程(请求...
  •   处理机是操作系统的核心资源,处理机管理时操作系统的核心功能,是为在多道程序系统中,提高处理机的使用效率。处理机管理好坏直接决定道程序操作系统的性能。   进程是处理机管理中最基本最核心的概念。...
  • Android多进程

    2016-05-16 20:10:00
    早期android系统只为一个进程应用分配了16M可用内存,随着手机硬件提升和android系统的改进,虽然可分配内存越来越多,但仍旧可以通过开启多进程来获取更多内存来处理自己App业务2 独立运行组件,...
  • 本实验模拟在单处理机情况下处理机调度问题,加深对进程调度理解。 二、实验内容 1. 优先权法、轮转法 简化假设 1) 进程为计算型(无I/O) 2) 进程状态:ready、running、finish 3) 进程需要CP...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 720
精华内容 288
关键字:

在单处理机的多进程系统中