两个正确的时间片轮转算法模拟(经测试,在特殊情况-'时间片为1时'也是正确的)
测试结果放在注释当中
代码1
[C] 纯文本查看 复制代码 #include<stdio.h>
#define N 50
struct PCB
{
int pn; //process name进程名字
int at; //arrival time到达时间
int st; //service time服务时间
int ct; //completion time完成时刻
int sc; //sign completion标志是否完成
int st1; //剩余服务时间
}process[N];
int sjp(int n)
{
int i, j, T;
printf("\n请输入时间片:\n");
scanf("%d", &T);
for (i = 1; i <= n; i++) //收集进程信息
{
process[i].sc = 0;
printf("\n%d:\n请依次输入进程的信息\n请输入pn:", i);
scanf("%d", &process[i].pn);
printf("请输入at:");
scanf("%d", &process[i].at);
printf("请输入st:");
scanf("%d", &process[i].st);
process[i].st1 = process[i].st;
}
for (i = 1; i <= n; i++)
for (j = i + 1; j <= n; j++) //按照各进程到达时间升序,对进程排序 注意:稳定的排序
{
if (process[j].at < process[i].at)
{
process[0] = process[j];
process[j] = process[i];
process[i] = process[0];
}
}
//for(i=1;i<=n;i++) //检查排序是否正确
//printf("%d\t",process[i].pn);
int time = process[1].at; //当前时间的初值
int flag = 1;
int sum = 0; //记录完成的进程数
printf("\n第几次调度进程 运行的进程pn 开始运行时间 运行时间 剩余服务时间 结束时间\n");
int z = 1; //记录第几次调度进程
while (sum < n)
{
flag = 0; //标志就绪队列中是否还有进程
for (i = 1; i <= n; i++) //时间片轮转法执行各进程
{
if (process[i].sc == 1) continue; //已完成的进程
else
{
if (process[i].st1 <= T && time >= process[i].at)//未完成的进程但是还需服务的时间少于等于一个时间片
{
flag = 1;
time = time + process[i].st1;
process[i].sc = 1;
process[i].ct = time;
printf("%8d%12d%15d%11d%11d%11d\n", z++, process[i].pn, time - process[i].st1, process[i].st1, 0, time);
process[i].st1 = 0;
}
else if (process[i].st1 > T&&time >= process[i].at)//未完成的进程但其还需服务时间至少大于一个时间片
{
flag = 1;
time = time + T;
process[i].st1 -= T;
printf("%8d%12d%15d%11d%11d%11d\n", z++, process[i].pn, time - T, T, process[i].st1, time);
}
if (process[i].sc == 1) sum++; //一个进程执行完就+1
}
}
if (flag == 0 && sum < n) // 还有没执行的进程,且没进入就就绪队列
{
for (i = 1; i <= n; i++)
if (process[i].sc == 0) { time = process[i].at; break; }
}
}
return 0;
}
int main()
{
int n;
printf("\t\t时间片轮转调度算法\n");
printf("请输入总进程数:\n");
scanf("%d", &n);
sjp(n);
return 0;
}
/*
时间片轮转调度算法
请输入总进程数:
5
请输入时间片:
1
1:
请依次输入进程的信息
请输入pn:1
请输入at:0
请输入st:4
2:
请依次输入进程的信息
请输入pn:2
请输入at:1
请输入st:3
3:
请依次输入进程的信息
请输入pn:3
请输入at:2
请输入st:5
4:
请依次输入进程的信息
请输入pn:4
请输入at:3
请输入st:2
5:
请依次输入进程的信息
请输入pn:5
请输入at:4
请输入st:4
第几次调度进程 运行的进程pn 开始运行时间 运行时间 剩余服务时间 结束时间
1 1 0 1 3 1
2 2 1 1 2 2
3 3 2 1 4 3
4 4 3 1 1 4
5 5 4 1 3 5
6 1 5 1 2 6
7 2 6 1 1 7
8 3 7 1 3 8
9 4 8 1 0 9
10 5 9 1 2 10
11 1 10 1 1 11
12 2 11 1 0 12
13 3 12 1 2 13
14 5 13 1 1 14
15 1 14 1 0 15
16 3 15 1 1 16
17 5 16 1 0 17
18 3 17 1 0 18
*/
代码2
[C] 纯文本查看 复制代码 #include<stdio.h>
#define MAX 10
struct task_struct
{
char name[10]; //进程名称
float arrivetime; //到达时间/
float starttime; //开始运行时间/
float runtime; //运行时间/
float finishtime; //运行结束时间/
int runflag; //调度标志/
int startflag; //是否为第一次开始调度
} tasks[MAX];
int counter; //实际进程个数/
int pinput();
int timecounter = 0;
int poutput(); //调度结果输出/
int time();
int charge();//判断是否所有的进程都被执行过
int time()
{
float temp = 0;//用来记录时间片已用长度
int i;
int j = 0;
int k = 0;
struct task_struct copy_task[MAX];//备份
for (i = 0; i < counter; i++)
{
copy_task[j++] = tasks[i];//对进程的初始化信息备份
}
temp = tasks[0].arrivetime;//temp=第一个进程的到达时间
while (charge())//while条件,charge为0跳出(说明进程都已经全部执行完毕),为1进入(进程还未执行完毕,继续执行)
{
for (i = 0; i < counter; i++)
{
if (tasks[i].arrivetime > temp)//如果第i个的到达时间大于第一个的到达时间,则将第i个的到达时间与temp交换,更新temp的记录,但是第一次运行的时候不走这一步
{
temp = tasks[i].arrivetime;
}
if (tasks[i].runflag == 0)//第i个进程还未结束
{
if (tasks[i].startflag == 0) //该条件成立则说明,该进程是第一次执行,记录开始执行时间
{
tasks[i].starttime = temp;//第一个进程的到达时间为temp
tasks[i].startflag = 1;//运行完上一步后记录该进程已经不是第一次运行了
}
if (tasks[i].runtime / timecounter > 1)//,运行时间除以时间片长度,说明至少有两倍的时间片未执行
{
tasks[i].runtime = tasks[i].runtime - timecounter;//剩余运行时间就等于原来运行时间减去一个时间片长度
temp = temp + timecounter;//temp继续记录已用的时间片长度
}
else if (tasks[i].runtime - timecounter == 0)//即运行时间除以时间片长度为1,该进程剩下的刚好是一个时间片长度,说明该进程只需在运行一一步就可以运行完毕
{
temp = temp + timecounter;//temp加上最后一个时间片长度就为该进程的结束时间
tasks[i].finishtime = temp;
tasks[i].runflag = 1;//标记该进程已经执行完毕
tasks[i].runtime = copy_task[i].runtime;//为了计算周转时间,运行时间从备份里面还原到最开始的运行时间
}
else//仅剩下不足一倍的时间片,则剩余运行时间除以时间片长度<1
{
temp = temp + tasks[i].runtime;//剩余运行时间不够一个时间片长度,则结束时间等于temp加上该进程的运行时间
tasks[i].finishtime = temp;
tasks[i].runflag = 1;//标记该进程已经运行完毕
tasks[i].runtime = copy_task[i].runtime;
}
}
}
}
return 0;
}
int charge()//判断是否全部进程都执行完毕
{
int k;
int superflag = 0;//判断是否全部的进程都执行完毕
for (k = 0; k < counter; k++)
{
if (tasks[k].runflag == 0)//只要
{
superflag = 1;
return superflag;
break;
}
else
{
superflag = 0;
}
}
return superflag;
}
int pinput() //进程参数输入/
{
int i;
printf("请输入进程个数:\n");
scanf("%d", &counter);
printf("请输入时间片长度:\n");
scanf("%d", &timecounter);
for (i = 0; i < counter; i++)
{
printf("******************************************\n");
printf("请输入进程名称、到达时间、运行时间:(中间用空格隔开)\n");
scanf("%s%f%f", tasks[i].name, &tasks[i].arrivetime, &tasks[i].runtime);
tasks[i].starttime = 0;
tasks[i].finishtime = 0;
tasks[i].runflag = 0; //运行是否结束
tasks[i].startflag = 0;//是否首次被执行
}
return 0;
}
int poutput() //调度结果输出
{
int i;
float zztime = 0, f1, w = 0;
printf("进程名 到达时间 运行时间 开始时间 结束时间 周转时间\n");
for (i = 0; i < counter; i++)
{
f1 = tasks[i].finishtime - tasks[i].arrivetime;
zztime += f1;
printf("%s\t%5.3f\t%5.3f\t%5.3f\t %5.3f\t%5.3f\n", tasks[i].name, tasks[i].arrivetime, tasks[i].runtime, tasks[i].starttime, tasks[i].finishtime, f1);
}
printf("平均周转时间=%5.2f\n", zztime / counter);
return 0;
}
void main()
{
pinput();
printf("时间片轮转算法。\n\n");
time();
poutput();
}
/*
请输入进程个数:
5
请输入时间片长度:
1
******************************************
请输入进程名称、到达时间、运行时间:(中间用空格隔开)
A 0 4
******************************************
请输入进程名称、到达时间、运行时间:(中间用空格隔开)
B 1 3
******************************************
请输入进程名称、到达时间、运行时间:(中间用空格隔开)
C 2 5
******************************************
请输入进程名称、到达时间、运行时间:(中间用空格隔开)
D 3 2
******************************************
请输入进程名称、到达时间、运行时间:(中间用空格隔开)
E 4 4
时间片轮转算法。
进程名 到达时间 运行时间 开始时间 结束时间 周转时间
A 0.000 4.000 0.000 15.000 15.000
B 1.000 3.000 1.000 12.000 11.000
C 2.000 5.000 2.000 18.000 16.000
D 3.000 2.000 3.000 9.000 6.000
E 4.000 4.000 4.000 17.000 13.000
平均周转时间=12.20
*/ |