操作系统实验一——模拟进程调度时间片轮转算法

原创 2006年05月21日 13:50:00

本程序用于模拟进程。
总体思路为:用一个调度线程来模拟操作系统的调度进程,用一个线程来模拟一个进程。于是,对应于每一个被模拟的进程,都有相应的线程来模拟,并在调度线程的调度下,实现时间片轮转的调度算法。
具体实现:
PCB块的数据结构:
typedef struct PCB {
 int id;
 char name[20];
 int status;
 int ax, bx, cx, dx;
 int pc;
 int psw;
 struct PCB* next;
 HANDLE hThis;
 DWORD threadID;
 int count;
}PCB, *pPCB;

ReadyList 和 FreeList的数据结构:
typedef struct {
 pPCB head;
 pPCB tail;
 int pcbNum;
}readyList, freeList, *pList;

状态列表:
enum STATUS { RUN, READY, WAIT };

PCB块总数:
const int PCB_LIMIT = 10;

在本程序中,调度线程为DWORD WINAPI scheduleThread(LPVOID lpParameter)。模拟进程的线程为:DWORD WINAPI processThread(LPVOID lpParameter)。

程序中每个时间片设置为1秒,其中每个进程在每个时间片内可以运行两条指令,将导致其pc加2。每个进程的各个寄存器,在进程生成时自动生成。

程序可以动态的创建进程,动态的撤销进程,并将最终的运行结果写在process_log.txt文件中。程序的运行界面如下:(可直接运行文件夹可执行程序中的Pro_test。)
create pro_name pro_len(如create p0 10)用于创建一个新进程。
remove pro_name (如remove p0)用于撤销一个进程。
current 用于显示当前运行进程以及当前就绪队列信息。

源代码如下:

pcb.h
#ifndef PCB_H
#define PCB_H

typedef struct PCB {
 int id;
 char name[20];
 int status;
 int ax, bx, cx, dx;
 int pc;
 int psw;
 struct PCB* next;
 HANDLE hThis;
 DWORD threadID;
 int count;
}PCB, *pPCB;

typedef struct {
 pPCB head;
 pPCB tail;
 int pcbNum;
}readyList, freeList, *pList;

typedef struct apply{
 char name[20];
 int time;
 struct apply* next;
}applyProcess, *applyList;

typedef struct {
 applyList head;
 applyList tail;
 int applyNum;
}applyQueue;

enum STATUS { RUN, READY, WAIT };
const int PCB_LIMIT = 10;

void init();
void createProcess(char* name, int ax);
void addApplyProcess(char* name, int time);
void createIfAnyApply();
void scheduleProcess();
void removeProcess(char* name);
void fprintReadyList();
void printCurrent();

#endif


pcb.cpp

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include "pcb.h"
#include "funCode.h"

pList   pReadyList = new readyList;
pList   pFreeList = new freeList;
pPCB   runPCB;
bool   firstTime = true;
applyQueue*  queue = new applyQueue;
HANDLE   hSchedule = NULL;
bool   schIsActive = false;
CRITICAL_SECTION cs_ReadyList;
CRITICAL_SECTION cs_SaveSection;
//CRITICAL_SECTION cs_RunPCB;

extern FILE* log;
extern PC;
extern FUN functions[FUN_NUM];

void initialPCB(pPCB p) {
 p->id = 0;
 strcpy(p->name, "");
 p->status = WAIT;
 p->ax = 0;
 p->bx = 0;
 p->cx = 0;
 p->dx = 0;
 p->pc = 0;
 p->psw = 0;
 p->next = NULL;
 p->hThis = NULL;
 p->threadID = 0;
 p->count = 0;
}

pPCB getPcbFromFreeList() {
 pPCB freePCB = NULL;
 if (pFreeList->head != NULL && pFreeList->pcbNum > 0) {
  freePCB = pFreeList->head;
  pFreeList->head = pFreeList->head->next;
  pFreeList->pcbNum--;
 }
 return freePCB;
}

void returnPcbToFreeList(pPCB p) {
 initialPCB(p);

 if (pFreeList->head == NULL) {
  pFreeList->head = p;
  pFreeList->tail = p;
  pFreeList->pcbNum++;
 } else {
  pFreeList->tail->next = p;
  pFreeList->tail = p;
  pFreeList->pcbNum++;
 }
}

DWORD WINAPI processThread(LPVOID lpParameter) {
 pPCB currentPcb = (pPCB)lpParameter;
 MSG msg;

 while (true) {
  Sleep(500);
  fprintf(log, "process %d:%s is running.../n", currentPcb->id, currentPcb->name);
  currentPcb->pc++;
  fflush(log);

  EnterCriticalSection(&cs_SaveSection);
  if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE)) {
   if (msg.message == WM_USER) {
    //printf("Process %d:%s recieve a message. It's to be suspended./n",
    // currentPcb->id, currentPcb->name);
   }
  }
  LeaveCriticalSection(&cs_SaveSection);
 }
 /*
 while (true) {
  PC = currentPcb->pc;
  
  for (int i = 0; i < TIME_SLOT; i++) {
   (*functions[PC%FUN_NUM].pc)();
   PC++;
  }
  
  currentPcb->pc = PC;
  SuspendThread(currentPcb->hThis);
 }*/

 return 0;
}

DWORD WINAPI scheduleThread(LPVOID lpParameter) {
 pList readyList = (pList)lpParameter;
 while (true) {
  scheduleProcess();

  if (readyList->pcbNum <= 0 && schIsActive) {
   schIsActive = false;
   SuspendThread(hSchedule);
  } else if (readyList->pcbNum >0 && !schIsActive) {
   schIsActive = true;
   ResumeThread(hSchedule);
  }
 }

 return 0;
}

void init() {
 ////////////////////////////////////////////////////////////////
 if (firstTime) {
  pReadyList->head = NULL;
  pReadyList->tail = NULL;
  pReadyList->pcbNum = 0;

  pFreeList->head = NULL;
  pFreeList->tail = NULL;
  pFreeList->pcbNum = 0;

  for (int i = 0; i < PCB_LIMIT; i++) {
   pPCB pTempPCB = new PCB;
   initialPCB(pTempPCB);
   pTempPCB->id = i;
   if (pFreeList->head == NULL) {
    pFreeList->head = pTempPCB;
    pFreeList->tail = pTempPCB;
    pFreeList->pcbNum++;
   } else {
    pFreeList->tail->next = pTempPCB;
    pFreeList->tail = pTempPCB;
    pFreeList->pcbNum++;
   }
  }

  hSchedule = CreateThread(NULL, NULL, scheduleThread, pReadyList, CREATE_SUSPENDED, 0);

  InitializeCriticalSection(&cs_ReadyList);
  InitializeCriticalSection(&cs_SaveSection);
  //InitializeCriticalSection(&cs_RunPCB);

  firstTime = false;
 }
 //////////////////////////////////////////////////////////////////////
}

void createProcess(char* name, int count/*, int pc*/) { 
 //
 EnterCriticalSection(&cs_ReadyList);
 //
 if (pFreeList->pcbNum > 0) {
  pPCB newPcb = getPcbFromFreeList();
  newPcb->status = READY;
  strcpy(newPcb->name, name);
  newPcb->count = count;
  //newPcb->pc = 0;
  newPcb->next = NULL;

  srand( (unsigned)time( NULL ) );
  newPcb->ax = rand() % 20;
  newPcb->bx = rand() % 20;
  newPcb->cx = rand() % 20;
  newPcb->dx = rand() % 20;
  newPcb->pc = rand() % 20;
  newPcb->psw = rand() % 20;
  
  if (pReadyList->pcbNum == 0) {
   pReadyList->head = newPcb;
   pReadyList->tail = newPcb;
   pReadyList->pcbNum++;
  } else {
   pReadyList->tail->next = newPcb;
   pReadyList->tail = newPcb;
   pReadyList->pcbNum++;
  }
  
  fprintf(log, "New Process Created.  /nProcess ID: %d  Process Name: %s  Process Length: %d/n",
   newPcb->id, newPcb->name, newPcb->count);
  fprintf(log, "AX: %d/tBX: %d/tCX: %d/tDX: %d/tPC: %d/tPSW: %d/n/n",
   newPcb->ax, newPcb->bx, newPcb->cx, newPcb->dx, newPcb->pc, newPcb->psw);
  fprintf(log, "Current ReadyList is:/n");
  fprintReadyList();

  newPcb->hThis = CreateThread(NULL, NULL, processThread, newPcb, CREATE_SUSPENDED, &(newPcb->threadID));
 } else {
  printf("PCB used out/n");
  fprintf(log, "New process intend to append. But PCB has been used out!/n/n");
 }
 //
 LeaveCriticalSection(&cs_ReadyList);
 //
}

void scheduleProcess() {
 ////
 //EnterCriticalSection(&cs_RunPCB);
 ////
 
 //
 EnterCriticalSection(&cs_ReadyList);
 //
 if (pReadyList->pcbNum > 0) {
  runPCB = pReadyList->head;
  
  pReadyList->head = pReadyList->head->next;
  if (pReadyList->head == NULL) {
   pReadyList->tail = NULL;
  }
  pReadyList->pcbNum--;

  runPCB->count--;
  fprintf(log, "Process %d:%s is to be scheduled./n"
   "Process %d:%s Information:/tAX: %d/tBX: %d/tCX: %d/tDX: %d/tPC: %d/tPSW: %d/n/n",
   runPCB->id, runPCB->name, runPCB->id, runPCB->name,
   runPCB->ax, runPCB->bx, runPCB->cx, runPCB->dx, runPCB->pc, runPCB->psw);
  ResumeThread(runPCB->hThis);
  runPCB->status = RUN;
  Sleep(1000);
  fprintf(log, "/nOne time slot used out!/n/n");
  runPCB->status = READY;
  PostThreadMessage(runPCB->threadID, WM_USER, 0, 0);
  //
  EnterCriticalSection(&cs_SaveSection);
  //
  SuspendThread(runPCB->hThis);
  //
  LeaveCriticalSection(&cs_SaveSection);
  //

  if (runPCB->count <= 0 && runPCB != NULL) {
   printf("/nProcess %d:%s has finished./n", runPCB->id, runPCB->name);
   printf("COMMAND>");
   fprintf(log, "Process %d:%s has finished./n/n", runPCB->id, runPCB->name);
   fprintf(log, "Current ReadyList is:/n");
   fprintReadyList();
   fflush(log);

   TerminateThread(runPCB->hThis, 0);
   returnPcbToFreeList(runPCB);
   runPCB = NULL;
  }
  
  if (runPCB != NULL) {
   if (pReadyList->pcbNum == 0) {
    pReadyList->head = runPCB;
    pReadyList->tail = runPCB;
   } else {
    pReadyList->tail->next = runPCB;
    pReadyList->tail = runPCB;
   }
   runPCB->next = NULL;
   runPCB = NULL;
   pReadyList->pcbNum++;
  }
 } else if (pReadyList != NULL) {
  pReadyList->head = NULL;
  pReadyList->tail = NULL;
  pReadyList->pcbNum = 0;
 }
 //
 LeaveCriticalSection(&cs_ReadyList);
 //
 ////
 //LeaveCriticalSection(&cs_RunPCB);
 ////
}

void addApplyProcess(char* name, int time) {
 applyProcess* newApply = new applyProcess;
 strcpy(newApply->name, name);
 newApply->time = time;
 newApply->next = NULL;
 
 if (queue->applyNum <= 0) {
  queue->head = newApply;
  queue->tail = newApply;
  queue->applyNum = 1;
 } else {
  queue->tail->next = newApply;
  queue->tail = newApply;
  queue->applyNum++;
 }

 createIfAnyApply();
}

void createIfAnyApply() {
 if (queue != NULL && queue->applyNum >= 1) {
  applyProcess* temp = queue->head;
  createProcess(temp->name, temp->time);
  
  if (queue->applyNum <= 1) {
   queue->head = NULL;
   queue->tail = NULL;
  } else {
   queue->head = queue->head->next;
  }
  
  queue->applyNum--;
  delete temp;
 }

 if (!schIsActive) {
  schIsActive = true;
  ResumeThread(hSchedule);
 }
}

void removeProcess(char* name) {
 pPCB removeTarget = NULL;
 pPCB preTemp = NULL;

 //
 EnterCriticalSection(&cs_ReadyList);
 //
 if (runPCB != NULL && strcmp(name, runPCB->name) == 0) {
  removeTarget = runPCB;
  
  printf("Process %d:%s has been removed./n", removeTarget->id, removeTarget->name);
  fprintf(log, "/nProcess %d:%s has been removed./n", removeTarget->id, removeTarget->name);
  
  TerminateThread(removeTarget->hThis, 0);
  returnPcbToFreeList(removeTarget);
  runPCB = NULL;

  fprintf(log, "Current ReadyList is:/n");
  fprintReadyList();
  fflush(log);

  //
  LeaveCriticalSection(&cs_ReadyList);
  //
  return;
 } else if (pReadyList->head != NULL) {
  for (removeTarget = pReadyList->head, preTemp = pReadyList->head;
   removeTarget != NULL; removeTarget = removeTarget->next) {

   if (removeTarget == pReadyList->head && strcmp(name, removeTarget->name) == 0) {
    pReadyList->head = pReadyList->head->next;
    if (pReadyList->head == NULL) {     
     pReadyList->tail = NULL;
    }
    
    printf("Process %d:%s has been removed./n", removeTarget->id, removeTarget->name);
    fprintf(log, "/nProcess %d:%s has been removed./n", removeTarget->id, removeTarget->name);
    
    TerminateThread(removeTarget->hThis, 0);
    returnPcbToFreeList(removeTarget);
    pReadyList->pcbNum--;

    fprintf(log, "Current ReadyList is:/n");
    fprintReadyList();
    fflush(log);

    //
    LeaveCriticalSection(&cs_ReadyList);
    //
    return;
   } else if (removeTarget != pReadyList->head && strcmp(name, removeTarget->name) == 0) {
    preTemp->next = removeTarget->next;
    if (removeTarget == pReadyList->tail) {
     pReadyList->tail = preTemp;
    }
    
    printf("Process %d:%s has been removed./n", removeTarget->id, removeTarget->name);
    fprintf(log, "/nProcess %d:%s has been removed./n", removeTarget->id, removeTarget->name);
    
    TerminateThread(removeTarget->hThis, 0);
    returnPcbToFreeList(removeTarget);
    pReadyList->pcbNum--;

    fprintf(log, "Current ReadyList is:/n");
    fprintReadyList();
    fflush(log);

    //
    LeaveCriticalSection(&cs_ReadyList);
    //
    return;
   } else if (removeTarget != pReadyList->head) {
    preTemp = preTemp->next;
   }
  }
 }
 
 printf("Sorry, there's no process named %s/n", name);
 //
 LeaveCriticalSection(&cs_ReadyList);
 //
 return;
}

void fprintReadyList() {
 pPCB tmp = NULL;
 tmp = pReadyList->head;
 if (tmp != NULL) {
  for (int i = 0; i < pReadyList->pcbNum; i++) {
   fprintf(log, "--%d:%s--", tmp->id, tmp->name);
   tmp = tmp->next;
  }
 } else {
  fprintf(log, "NULL");
 }
 fprintf(log, "/n/n");
}

void printReadyList() {
 pPCB tmp = NULL;
 tmp = pReadyList->head;
 if (tmp != NULL) {
  for (int i = 0; i < pReadyList->pcbNum; i++) {
   printf("--%d:%s--", tmp->id, tmp->name);
   tmp = tmp->next;
  }
 } else {
  printf("NULL");
 }
 printf("/n/n");
}

void printCurrent() {
 if (runPCB != NULL) {
  printf("Process %s is running.../n", runPCB->name);
 } else {
  printf("No process is running./n");
 }
 printf("Current readyList is:/n");
 printReadyList();
}


main.cpp

#include <stdio.h>
#include <string.h>

#include <windows.h>

#include "pcb.h"
#include "funCode.h"

FILE *log;
int PC = 0;

extern applyQueue* queue;

void helpInfo() {
 printf("/n************************************************/n");
 printf("COMMAND LIST:/n");
 printf("create process_name process_length (create p0 8)/n"
  "/t append a process to the process list/n");
 printf("remove process_name (remove p0)/n"
  "/t remove a process from the process list/n");
 printf("current/t show current runProcess readyList/n");
 printf("exit/t exit this simulation/n");
 printf("help/t get command imformation/n");
 printf("************************************************/n/n");
}

main() {
 queue->head = NULL;
 queue->tail = NULL;
 queue->applyNum = 0;

 log = fopen("Process_log.txt", "w");
 funsInitial();

 helpInfo();
 init();

 char command[20] = {0};
 while (strcmp(command, "exit") != 0) {
  printf("COMMAND>");
  scanf("%s", command);
  
  if (strcmp(command, "exit") == 0) {
   break;
  }else if (strcmp(command, "create") == 0) {
   char name[20] = {'/0'};
   int time = 0;
   scanf("%s %d", name, &time);

   addApplyProcess(name, time);
  } else if (strcmp(command, "remove") == 0) {
   char name[20] = {'/0'};
   scanf("%s", name);
   
   removeProcess(name);
  } else if (strcmp(command, "current") == 0) {
   printCurrent();
  } else if (strcmp(command, "help") == 0) {
   helpInfo();
  } else {
   printf("Enter help to get command information!/n");
  }
 }

 fclose(log);

 return 0;
}

 

 

 

进程调度(二)——时间片轮转算法

一 定义时间片轮转算法是将所有的就绪进程按先来先服务的原则,排成一个队列,按时间片轮转。时间片的大小从几ms到几百ms。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进...
  • qq_30091945
  • qq_30091945
  • 2017年03月12日 14:50
  • 1172

操作系统 时间片轮转调度算法

时间片轮转法(RR) 算法描述:用于分时系统中的进程调度。每次调度时,总是选择就绪队列的队首进程,让其在CPU上运行一个系统预先设置好的时间片。一个时间片内没有完成运行的进程,返回到绪队列末尾重新排队...
  • u013630349
  • u013630349
  • 2015年08月17日 21:34
  • 14981

进程调度:时间片轮转调度算法

一、实验目的 (1) 加深对进程的理解 (2) 理解进程控制块的结构 (3) 理解进程运行的并发性 (4) 掌握时间片轮转法进程调度算法 二、实验原理 (1)建立进程控制块 (2)...
  • FengNingXueChen
  • FengNingXueChen
  • 2016年11月24日 14:43
  • 6287

c++模拟操作系统进程调度算法(优先数,时间片轮转)

实验一 进程调度 1.目的和要求 进程调度是处理机管理的核心内容。本实验要求编写和调试一个简单的进程调度程序。通过本实验可以加深理解有关进程控制块、进程队列的概念,体会了解优先数和时间片轮转调度...
  • Dove_MrQ
  • Dove_MrQ
  • 2015年04月27日 12:24
  • 3994

【操作系统 - 2】时间片轮转RR进程调度算法

【操作系统 - 2】时间片轮转RR进程调度算法。学习至此,发现很多学了但很久没用的知识,久而久之,慢慢遗忘。等哪天还需要的话,却发现已经忘得差不多了,即使整理了文档(word等),还是得从头再学一遍。...
  • Houchaoqun_XMU
  • Houchaoqun_XMU
  • 2017年03月17日 23:56
  • 4355

操作系统实验二(调度算法模拟-先进先出-时间片轮转法-优先服务调度算法)

实验二 进程调度 一、     实验目的 1.       理解进程运行的并发性。  2.       理解处理器的三级调度。 3.       掌握先来先服务的进程调度算法。 4.    ...
  • GoodLuckAC
  • GoodLuckAC
  • 2016年05月26日 20:40
  • 6396

时间片轮转算法和优先级调度算法 C语言模拟实现

一、目的和要求进程调度是处理机管理的核心内容。本实验要求用高级语言编写模拟进程调度程序,以便加深理解有关进程控制快、进程队列等概念,并体会和了解优先数算法和时间片轮转算法的具体实施办法。二、实验内容1...
  • eaglewood2005
  • eaglewood2005
  • 2009年07月24日 19:26
  • 36461

优先级的时间片轮转算法(操作系统实验)

实验题目: 基于优先数的时间片轮转调度算法调度处理器一、实验目的 在采用多道程序设计的系统中,同时处于就绪态的进程往往有多个,当就绪态的进程数大于处理器的个数时,就需按照某种策略进行分配处理器。本...
  • magicianofcodes
  • magicianofcodes
  • 2016年11月21日 23:15
  • 565

时间片轮转调度算法的C语言模拟实现

时间片轮转调度是一种最古老,最简单,最公平且使用最广的算法。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。如果在时间片结束时进程还在运行,则CPU将被剥夺并分配给另一个进程。如果进...
  • u010480899
  • u010480899
  • 2016年04月17日 12:23
  • 6026

实时操作系统的任务调度示例之时间片

摘要 本文用几个小实验来清晰的展示时间片轮转调度的运行情况,以及时间片的配置对于应用程序的影响。后面分析了整个过程的软硬件实现原理,最后给出了关于时间片配置的一些建议。 在图中,一共有3个用户...
  • wbwwf8685
  • wbwwf8685
  • 2016年07月18日 11:07
  • 3900
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:操作系统实验一——模拟进程调度时间片轮转算法
举报原因:
原因补充:

(最多只允许输入30个字)