请编写一个程序,模拟若干进程调度执行的情况。假设进程的状态分为执行和就绪两种。每个进程以其PCB为代表即可,无需创建真正的进程。
```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define free 0
#define ready 1
#define running 2
#define ts 2 /* time slice */
//函数定义
void init(int );
struct PCB* readyQueueToRunningQueue(struct PCB *);
void runningQueneToReadyQuene(struct PCB *);
void runningQueneToFreeQuene(struct PCB *);
void paraInit(struct PCB *,int ,int );
void prpcb(struct PCB* );
void scheduling();
int input();
struct PCB {
int pid; /* 进程ID */
int pstate; /* 进程状态 */
char pname[3]; /* 映象名称 */
int ptime; /* 剩余运行时间 */
struct PCB *pnext; /* 下一个PCB */
} ;
struct PCBQUENE{
struct PCB head;
int qNum;
}freeQueue,readyQueue,runningQueue; //创建三个队列
int main() //主函数入口
{
srand(time(0));
int num = input();
init(num);
scheduling();
printf("---------------------------------------------------------------------------\n");
printf("freeQuene:\n");
printQuene(&freeQueue);
printf("Hello world!\n");
getchar();
getchar();
return 0;
}
void init(int n){ //初始化函数
struct PCB *pcb,*p;
pcb = (struct PCB*)calloc(n,sizeof(struct PCB));
for(int i=0;i<n;i++){ //创建PCB
paraInit(&pcb[i],i,i);
prpcb(&pcb[i]);
}
runningQueue.head.pnext = &pcb[0]; //设置运行队列头结点
runningQueue.head.pnext->pstate = running;
pcb[0].pstate = running;
printf("当前%s运行态,%d\n",pcb[0].pname,pcb[0].pstate);
runningQueue.qNum = 1;
readyQueue.head.pnext = &pcb[1]; //设置准备队列头结点
readyQueue.qNum = 1;
p = &pcb[1];
for(int i=2;i<n;i++){
p->pnext = &pcb[i];
p = p->pnext;
readyQueue.qNum++;
}
}
void printQuene(struct PCBQUENE* pcbquene){ //打印队列信息
struct PCB *p;
p = pcbquene->head.pnext;
while(p!=NULL){
prpcb(p);
p = p->pnext;
}
}
struct PCB* readyQueueToRunningQueue(struct PCB *pcb){ //准备进程加入运行队列
struct PCB *pold;
pcb->pstate = 2;
pold = runningQueue.head.pnext;
runningQueue.head.pnext = pcb;
readyQueue.head.pnext = pcb->pnext;
pcb->pnext = NULL;
printf("---------------------------------------------------------------------------\n");
printf("\t\t\t\t\tSched: %s(Ready -> Running)\n",pcb->pname);
return pold; //原先运行进程返回准备插入其他队列
}
void runningQueneToReadyQuene(struct PCB *pcb){ //运行进程插入就绪队列
struct PCB *p,*pold;
pcb->pstate = 1;
int n = 0;
p = readyQueue.head.pnext;
while(p){ //遍历readyquene节点个数
n++;
p = p->pnext;
}
if(n>0){
n = rand()%n; //随机插入readyquene的位置
p = readyQueue.head.pnext;
while(n>=1){
n--;
p = p->pnext;
}
pold = p;
p = p->pnext;
pold->pnext = pcb; //插入readyqueen
pcb->pnext = p;
}
else{
readyQueue.head.pnext = pcb;
}
printf("\t\t\t\t\tSched: %s(Running -> Ready)\n",pcb->pname);
}
void runningQueneToFreeQuene(struct PCB *pcb){ //运行进程插free队列
struct PCB *p,*pold;
pcb->pstate = 0;
p = freeQueue.head.pnext;
if(p==NULL){
freeQueue.head.pnext = pcb;
pcb->pnext = NULL;
}
else{
while(p){
pold = p;
p = p->pnext;
}
pold->pnext = pcb;
pcb->pnext = NULL;
}
printf("\t\t\t\t\tSched: %s(Running -> Free)\n",pcb->pname);
}
void prpcb(struct PCB* p) //打印pcb节点信息
{
printf("pname:%s,",p->pname);
printf("pid:%d,", p->pid);
printf("pstate:%d,", p->pstate);
printf("ptime:%d\n", p->ptime);
}
void paraInit(struct PCB *pcb,int i,int ptime){ //参数初始化
pcb->pid = i;
sprintf(pcb->pname,"P%d",i);//int转字符串函数
pcb->pstate = ready;
pcb->ptime = rand()%10 +2 ; //随机时间片>0
printf("%s初始化完成\n",pcb->pname);
}
void scheduling(){ //调度器
struct PCB *p = readyQueue.head.pnext ,*q = runningQueue.head.pnext,*r;
int time = runningQueue.head.pnext->ptime;
while(p || q){
if(p){ //判断是否有等待进程
if (time>=ts)time = ts;
Sleep(time*300); //睡眠时间 ms
q->ptime-=time;
r=readyQueueToRunningQueue(p);
if (q->ptime<=0){
runningQueneToFreeQuene(r);
}
else runningQueneToReadyQuene(r);
p = readyQueue.head.pnext;
q = runningQueue.head.pnext;
time = q->ptime;
printf("readyQuene:\n");
printQuene(&readyQueue);
printf("runningQuene:\n");
printQuene(&runningQueue);
}
else { //无就绪队列
Sleep(time*300);
q->ptime = 0;
runningQueneToFreeQuene(q);
q = NULL;
}
}
}
int input(){
int num ;
printf("input process number please:");
while(!scanf("%d",&num)){
fflush(stdin); //清空缓存
printf("it's not a number! try again\n");
}
return num;
}