操作系统课程设计——时间片轮转算法模拟

代码实现:

#include <iostream>
#include <stdio.h>
#include <malloc.h>

typedef struct node
{
     char name;//进程名称 
     int arrive_time;//到达时间
     int need_time;//需要的运行时间
     int res_time;//剩余运行时间
     int finished_time;//完成时间
     int turn_time;//周转时间 = 完成时间 - 到达时间 
     int weight_turn_time;//带权周转时间 = 周转时间 /运行时间 
     char flag;//记录进程当前状态
     struct node *next;
}PCB;

PCB* CreateList(int n)//创建进程队列
{
      printf("开始创建进程啦:\n");//创建进程队列提示语句 
      PCB *head=(PCB*)malloc(sizeof(PCB));//分配存放头节点的指针 
      PCB *q=(PCB*)malloc(sizeof(PCB));//进程队列q 
      
      for(int i=0;i<n;i++)//n重循环输入n个进程的信息 
      {
           PCB *pnew=(PCB*)malloc(sizeof(PCB));//用于存放当前进程的信息 
           if(i==0)//头节点指向第一个进程 
               head->next=pnew;
           printf("请输入第%d个进程的名字,到达时间和服务时间\n",i+1);//物理位序和逻辑位序相差1 
           getchar();//吸收掉缓冲区可能存在的字符 
           scanf("%c%d%d",&pnew->name,&pnew->arrive_time,&pnew->need_time);//输入当前进程的相关信息 
           pnew->flag='R';//设置进程状态为未在运行 
           pnew->res_time=pnew->need_time;//初始化需要的剩余运行时间为运行时间 
           pnew->next=NULL;//置头节点的下一个为空指针域 
           //采用尾插法将该进程插入到 q之后 
		   q->next=pnew;
           q=pnew;
           //getchar();
       }
       q->next=NULL;//尾节点的指针域置为 NULL; 
       q=NULL;
       free(q);//释放掉q的空间,此时还有head指向该队列 
       return head;//返回头节点 
}

void Push(PCB *p,PCB *t)//将新进程 t加入到 p队列中
{
    PCB *q=p; 
    while(q->next)//使q指向队列的最后一个元素 
    {
        q=q->next;
     }
     q->next=t;//将t接入到队列的最后一个元素之后,尾插法 
     t->next=NULL;//置最后一个节点的下一个指针域为 NULL 
}

PCB* Pop(PCB *p)//弹出队首进程
{
    PCB *top=(PCB*)malloc(sizeof(PCB));//为top指针申请内存空间 
    top=p->next;//top指向队首进程 
    p->next=p->next->next;//删除队首进程 
	top->next=NULL;//返回队首进程不影响队列其余元素,置top后继节点为空 
    return top;//返回队首进程 
}

void sort(PCB *p,int n)//按照队列中进程的到达时间进行排序
{
      PCB *r,*q;
      bool exchange;//标记此趟比较是否有数进行了交换 
      //利用冒泡排序进行排序 
      for(int i=0;i<n;i++)
      {
          q=p;///q指向要排序的队列
		  exchange=false; 
          for(int j=0;j<n-i-1;j++)//冒泡排序每趟比较出一个最小值,所以每趟的比较次数递减 
          {
                r=q->next;//r指向要比较的第二个数
				//q指向要比较的第一个数 
                if(r->arrive_time<q->arrive_time)//若第一个数比第二个数大,则交换 
                {
                      q->next=r->next;//将q放在r之后 
                      r->next=q;//将r放在q之前 
                      exchange=true;
                 }
                q=q->next; 
            }
            if(!exchange) break; 
       }
}

void Run(PCB *p,int n,int piece)//运行进程
{
     sort(p,n);//按照进程到达时间排序
     PCB *cur=p;//当前运行进程
     PCB *pool=p;//剩余未运行的进程队列
     PCB *ready=(PCB *)malloc(sizeof(PCB));//就绪队列,含有头结点
     ready->next=NULL;
     int now_time=0;//当前时间
     PCB *s;//用于打印进程队列的进程信息
     //寻找第一个可执行进程
     while(1)
     {
     	//p队列的第一个是头节点 
         if(pool->next->arrive_time>now_time)//如果当前进程的到达时间大于当前时间,则表示当前进程不可执行 
              now_time++;//但由于该队列已排序,所以当前时间段内没有进程到达,now_time++; 
         else//找到了可运行的进程 
         {
			 PCB *temp=Pop(pool);
             Push(ready,temp);//将进程池中的首进程弹出,放入就绪队列ready中 
             break;
         }
      }

     while(1)
     {
         //寻找可以调度的进程
         if(ready->next)//如果就绪队列不为空 
         {
             cur=Pop(ready);//将就绪队列队首进程弹出并进入当前运行的进程队列 
             //打印正在运行的进程信息
             printf("正在运行的进程如下:\n");
             printf("进程名称 到达时间  服务时间 已运行时间 剩余运行时间\n");
             printf("%c \t    %d    \t %d    \t %d    \t %d\n",cur->name,cur->arrive_time,cur->need_time,cur->need_time-cur->res_time,cur->res_time);

             //进程运行
             int slice=piece;//slice为时间片 
             while(cur->res_time&&slice)//当当前进程的还需运行时间大于0并且当前时间片大于0时,可以继续运行 
             {
                   slice--;//当前时间片减一 
                   now_time++;//时间加一 
                   cur->res_time--;//当前进程的还需运行时间减一 
                   if(pool->next&&pool->next->arrive_time<=now_time)//当前时间变化,判断是否有可加入就绪队列的进程 
                   {
					    PCB *temp=Pop(pool);
                        Push(ready,temp);//将进程池中的进程弹出并加入就绪队列 
                   }
             }
              //打印当前就绪队列中的进程
			  printf("******************************************************此时的时间点为%d\n",now_time);
              printf("进程%c执行一次后就绪队列中的进程如下:\n",cur->name);
              
              printf("进程标识 到达时间  服务时间 已运行时间 还剩运行时间\n");
			  //检查当前进程是否运行结束
             if(cur->res_time>0)//进程运行未结束
                   Push(ready,cur);//将该进程重新加入就绪队列队尾  
             else//进程运行结束,释放内存
			 {
                   cur->flag='C';//标记进程状态为C,已运行完成 
				   PCB *temp=cur;
				   temp=NULL;
				   free(temp);//释放运行完的进程PCB的空间 
				   cur=NULL; //置当前运行的进程为空
				    
			 }
			 s=ready->next;
			 //输出就绪队列中尚未运行完的进程的信息 
             while(s)
             {

                 if(s->flag=='R')
				     printf("%c \t    %d    \t %d    \t %d    \t %d\n",s->name,s->arrive_time,s->need_time,s->need_time-s->res_time,s->res_time);
                 s=s->next;
             }
             //判断是否所有进程都执行结束
             if(pool->next==NULL&&ready->next==NULL){
             	printf("所有进程运行结束!!\n太棒啦!!!!!\n");break;
			 }
			 else{
			 	printf("进程运行尚未完成,同志仍需努力!\n");
			 }
              printf("\n");
          }
          else//就绪队列为空,进程池不为空
          {
             while(1)
             {
                    if(pool->arrive_time>now_time)//若该进程不可运行 
                        now_time++;
                     else//若该进程可以运行 
                    {
						PCB *temp=Pop(pool);
                        Push(ready,temp);//将该进程从进程池中弹出放入就绪队列中去。 
                        break;//找到可运行进程,退出该循环 
                    }
               }
           }
	 }
}

int main()
{
	printf("\n请输入进程数目以及时间片(n m):"); 
    int n;
    int piece;
    scanf("%d%d",&n,&piece);
    PCB *p=CreateList(n);
    Run(p,n,piece);
    return 0;
}

/*
2 2
1 0 2
2 1 1
*/

  

 

 

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值