这有点古怪.我不确定我对这个问题有一个明确的答案.
TL;DR是我think网站可能关闭(稍后会有更多内容).
但是,你的代码有are个问题...
- 你的主循环[AFAICT]错误:
- 它假设到给定进程执行时,主时钟大于到达时间.
- 对于给定的示例,这是true,到达时间为:0,5,8,15,20
- 这将失败(例如)如果
D
的到达时间为T50而不是T15,
- 不需要用
double
—int
就行了.
- 输出有太多的制表符,很难阅读.
- 你只是在打印最终结果.如果流程状态打印在each次迭代上,它将显示历史(可以与网站的甘特图匹配).
- 中间结果几乎立即偏离.
- 有许多"松散"变量(例如
utilised_cpu_time
,total_turnaround_time
等).代码可以简化,将它们放在struct
中,并只传递一个single指针到struct
.
- 你做了很多(例如)
processes[i].whatever
而不是定义指针(例如)Process *p = &processes[i];
然后使用p->whatever
.
- 在您的主循环中,您需要在中间做
i = -1;
次才能重新开始.这有点老生常谈.干净(呃)的方法是使用嵌套循环.
以下是网站的输入:
Here is the website's Gantt chart:
The issue: [我可能完全错了,但是]在时间T30,进程D is是可运行的(E也是),所以序列应该从以下开始:
A B C D E A B C D E
但是,Gantt图表的顺序是:
A B C A D E B
换句话说,该网站确实有not人认为D
人是可以运行的.
因此,也许,该网站的"到达时间"的概念是不同的(或者它有某种缺陷?)
以下是网站的最终结果
这不匹配太好的结果无论是你的程序(或你的程序重组由我).
基于我上面提到的所有问题,我不得不对你的代码进行了一点重组.
- 我在查看代码并试图理解其逻辑时,一次做了一点点.
- 我清理并简化了我认为可能有问题的东西.
- 我重新做了主循环以适应问题[我感觉到]与not尊重延误由于到达时间.
- 注意,我[可能] broke "响应时间"计算在
calc_response_time
- 我认为代码的其余部分是好的,但是,我可以 destruct 其他东西以及.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
typedef struct Process {
int pidx;
int arrival_time;
int burst_time;
int finish_time;
int remaining_time;
int wait_time;
int turnaround_time;
int response_time;
int first_run;
int pgive;
} Process;
Process *processes;
typedef struct {
int slice_numproc; // number of processes
int slice_quantum; // length of time slice
int slice_remainder; // remainder of current time slice
int slice_round; // slice round
int slice_clock; // current time (utilised_cpu_time)
int slice_start; // start time
int slice_pcur; // index of current process
int slice_completed; // number of completed processes
Process slice_ptot; // totals
} Slice;
void print_process_timings(Process *p,Slice *slice,int nlflg);
void print_header(const char *msg);
void prtint(int val);
void prtrnge(int v1,int v2);
void prtsep(const char *msg);
// Function to calculate the response time of each process
void
calc_response_time(Process *pold,Process *pcur)
{
int prev_process_cpu_time = pold->burst_time - pold->remaining_time;
pcur->response_time = pold->response_time + prev_process_cpu_time;
pcur->first_run = 0;
}
// Function to simulate the execution of a process by the CPU
#if 0
void
execute_process(int i, int time_slice, double *utilised_cpu_time, int *num_processes_completed, double *total_wait_time, double *total_turnaround_time, double *total_response_time)
{
if (processes[i].remaining_time > time_slice) {
*utilised_cpu_time += time_slice;
processes[i].remaining_time -= time_slice;
}
else if (processes[i].remaining_time <= time_slice) {
*utilised_cpu_time += processes[i].remaining_time;
processes[i].remaining_time = 0;
processes[i].turnaround_time = *utilised_cpu_time;
processes[i].wait_time = *utilised_cpu_time - processes[i].burst_time;
*total_wait_time += processes[i].wait_time;
*total_turnaround_time += processes[i].turnaround_time;
*total_response_time += processes[i].response_time;
(*num_processes_completed)++;
}
}
#else
void
execute_process(Process *p, Slice *slice)
{
int pgive = slice->slice_quantum;
if (pgive > p->remaining_time)
pgive = p->remaining_time;
int doneflg = (pgive >= p->remaining_time);
slice->slice_clock += pgive;
p->remaining_time -= pgive;
p->pgive = pgive;
if (doneflg) {
p->wait_time = slice->slice_clock - p->burst_time;
p->finish_time = slice->slice_clock;
p->turnaround_time = p->finish_time - p->arrival_time;
Process *ptot = &slice->slice_ptot;
ptot->wait_time += p->wait_time;
ptot->turnaround_time += p->turnaround_time;
ptot->response_time += p->response_time;
slice->slice_completed += 1;
}
}
#endif
// process_old -- Execute processes and calculate timings
void
process_old(Slice *slice)
{
int first_run = 1;
for (int i = 0; i < slice->slice_numproc; i++) {
Process *pcur = &processes[i];
#if 0
if (processes[i].remaining_time != 0) {
execute_process(i,time_slice,
&utilised_cpu_time,&num_processes_completed,&total_wait_time,
&total_turnaround_time,&total_response_time);
}
#else
if (pcur->remaining_time != 0)
execute_process(pcur,slice);
#endif
if (i > 0 && first_run) {
calc_response_time(pcur - 1,pcur);
if (i == slice->slice_numproc - 1) {
first_run = false;
}
}
if (i == slice->slice_numproc - 1 &&
slice->slice_completed < slice->slice_numproc) {
// Reset loop if there are outstanding processes
i = -1;
}
else if (slice->slice_completed == slice->slice_numproc) {
// Exit loop if all processes are completed
break;
}
}
}
void
process_new(Slice *slice)
{
Process *pold = NULL;
#if 0
print_header();
#endif
slice->slice_round = 0;
while (slice->slice_round < 100) {
Process *pcur = &processes[slice->slice_pcur];
do {
// process is done
if (pcur->remaining_time == 0)
break;
slice->slice_start = slice->slice_clock;
// process not yet started
if (slice->slice_start < pcur->arrival_time)
break;
execute_process(pcur,slice);
if ((pold != NULL) && pcur->first_run)
calc_response_time(pold,pcur);
pold = pcur;
if ((slice->slice_round % slice->slice_numproc) == 0)
print_header(NULL);
print_process_timings(pcur,slice,0);
printf("\n");
} while (0);
// Exit loop if all processes are completed
if (slice->slice_completed >= slice->slice_numproc)
break;
// try next in round robin
slice->slice_pcur += 1;
slice->slice_pcur %= slice->slice_numproc;
}
}
int getstr(char *buf,int buflen,const char *prompt);
long getnum_strtol(const char *prompt);
int
main(int argc,char **argv)
{
//char input[12];
#if 0
bool first_run = true;
int num_processes_completed = 0;
double utilised_cpu_time = 0;
double total_wait_time = 0;
double total_turnaround_time = 0;
double total_response_time = 0;
#endif
--argc;
++argv;
if (argc > 0) {
close(0);
open(*argv,O_RDONLY);
}
Slice slice = { 0 };
// Print introduction
printf("CPU scheduling method: Round Robin (RR)\n\n");
// Prompt user to enter the number of processes
slice.slice_numproc = getnum_strtol("Enter the number of processes");
printf("\n");
if (slice.slice_numproc == -1) {
printf("Please input a valid non-negative integer!\n");
return 1;
}
// Allocate memory for processes
processes = calloc(slice.slice_numproc,sizeof(Process));
// Check if memory allocation failed
if (processes == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
// Input burst times and arrival times for each process
char prompt[100];
for (int i = 0; i < slice.slice_numproc; i++) {
Process *p = &processes[i];
p->pidx = i;
sprintf(prompt,"Enter Burst Time for process %d", i + 1);
p->burst_time = getnum_strtol(prompt);
sprintf(prompt,"Enter Arrival Time for process %d", i + 1);
p->arrival_time = getnum_strtol(prompt);
printf("\n");
// Check if input is invalid
if (p->burst_time < 0 || p->arrival_time < 0) {
printf("Please input valid non-negative integers!\n");
free(processes);
return 1;
}
p->response_time = 0;
p->turnaround_time = 0;
p->wait_time = 0;
p->remaining_time = p->burst_time;
p->first_run = 1;
#if 0
else {
// Initialize a new process instance
Process p;
p.response_time = 0;
p.arrival_time = arrival_time;
p.turnaround_time = 0;
p.wait_time = 0;
p.burst_time = burst_time;
p.remaining_time = burst_time;
processes[i] = p;
}
#endif
}
// Input the size of time slice
slice.slice_quantum = getnum_strtol("Enter the size of time slice");
// Check if input is invalid
if (slice.slice_quantum <= 0) {
printf("Please input a valid non-negative integer!\n");
free(processes);
return 1;
}
prtsep("INITIAL CONDITIONS");
print_header(NULL);
for (int i = 0; i < slice.slice_numproc; i++) {
Process *p = &processes[i];
print_process_timings(p,&slice,1);
}
prtsep("HISTORY/GANTT");
process_new(&slice);
// Print timings for each process
// Print header for process timings
prtsep("FINAL");
print_header(NULL);
for (int i = 0; i < slice.slice_numproc; i++) {
Process *p = &processes[i];
print_process_timings(p,&slice,1);
}
print_process_timings(&slice.slice_ptot,&slice,1);
printf("\n");
// Print average waiting time, turnaround time, and response time
printf("Average Waiting Time: %.1f\n",
slice.slice_ptot.wait_time / (double) slice.slice_numproc);
printf("Average Turnaround Time: %.1f\n",
slice.slice_ptot.turnaround_time / (double) slice.slice_numproc);
printf("Average Response Time: %.1f\n",
slice.slice_ptot.response_time / (double) slice.slice_numproc);
// Free allocated memory for processes
free(processes);
return 0;
}
struct phdr {
const char *str;
int len;
int off;
void (*prt)(struct phdr *phdr,Process *p,Slice *slice);
};
void
prtround(struct phdr *phdr,Process *p,Slice *slice)
{
prtint(slice->slice_round++);
}
void
prtclock(struct phdr *phdr,Process *p,Slice *slice)
{
prtrnge(slice->slice_start,slice->slice_clock - 1);
}
#define OFFOF(_sym) \
((size_t) &((Process *) 0)->_sym)
#define PHDR2(_str,_sym) \
{ .str = _str, .off = OFFOF(_sym) }
#define PHDRX(_str,_fnc) \
{ .str = _str, .off = -1, .prt = _fnc }
struct phdr hdrlist[] = {
PHDR2("P(i)",pidx),
PHDR2("Arrival Time",arrival_time),
PHDR2("Burst Time",burst_time),
PHDR2("Finish Time",finish_time),
PHDR2("Turn Around",turnaround_time),
PHDR2("Wait Time",wait_time),
PHDR2("Resp Time",response_time),
PHDR2("Remain Time",remaining_time),
PHDR2("Give",pgive),
#if 1
PHDRX("Round",prtround),
PHDRX("Clock Range",prtclock),
#endif
};
#define countof(_arr) \
(sizeof(_arr) / sizeof(_arr[0]))
#define PHDRFOR \
struct phdr *phdr = &hdrlist[0]; \
phdr < &hdrlist[countof(hdrlist)]; \
++phdr
const char *
phdrstr(struct phdr *phdr,int idxneed)
{
static char buf[100];
strcpy(buf,phdr->str);
char *bp = buf;
const char *tok = NULL;
for (int idxcur = 0; ; ++idxcur) {
tok = strtok(bp," ");
if (tok == NULL)
break;
bp = NULL;
if (idxcur == idxneed)
break;
}
if (tok == NULL) {
buf[0] = 0;
tok = buf;
}
return tok;
}
void
pfill(struct phdr *phdr,int len)
{
for (; len < phdr->len; ++len)
fputc(' ',stdout);
printf(" ");
}
// Function to print header for process timings
void
print_header(const char *msg)
{
const char *str;
int iline;
printf("\n");
static int count = 0;
if (count == 0) {
for (PHDRFOR) {
iline = 0;
phdr->len = 0;
while (1) {
str = phdrstr(phdr,iline++);
if (str[0] == 0)
break;
if (iline > count)
count = iline;
int curlen = strlen(str);
if (curlen > phdr->len)
phdr->len = curlen;
}
}
}
if (msg != NULL)
printf("%s\n",msg);
for (iline = 0; iline < count; ++iline) {
for (PHDRFOR) {
str = phdrstr(phdr,iline);
int len = printf("%s",str);
pfill(phdr,len);
}
printf("\n");
}
}
int pidx;
void
prtint(int val)
{
struct phdr *phdr = &hdrlist[pidx++];
int len = printf("%d",val);
pfill(phdr,len);
}
void
prtrnge(int v1,int v2)
{
struct phdr *phdr = &hdrlist[pidx++];
int len = printf("%d-%d",v1,v2);
pfill(phdr,len);
}
void
prtsym(struct phdr *phdr,Process *p,Slice *slice)
{
void *vp = p;
vp += phdr->off;
int *valp = vp;
if (phdr->prt != NULL)
phdr->prt(phdr,p,slice);
else
prtint(*valp);
}
void
prtsep(const char *msg)
{
int len = strlen(msg);
int margin = 80 - len - 2;
margin /= 2;
printf("\n");
int col = 0;
for (int wid = margin; wid > 0; --wid, ++col)
printf("-");
col += printf(" %s ",msg);
for (; col < 80; ++col)
printf("-");
printf("\n");
}
// Function to print timings for an individual process
void
print_process_timings(Process *p, Slice *slice, int nlflg)
{
pidx = 0;
for (PHDRFOR)
prtsym(phdr,p,slice);
#if 0
prtint(i + 1);
prtint(p->arrival_time);
prtint(p->burst_time);
prtint(p->finish_time);
prtint(p->turnaround_time);
prtint(p->wait_time);
prtint(p->response_time);
prtrnge(p->remaining_time + p->pgive,p->remaining_time);
prtint(p->pgive);
#endif
if (nlflg)
printf("\n");
}
// getstr -- get a string with prompt
// RETURNS: length or (<0 -> error)
int
getstr(char *buf,int buflen,const char *prompt)
{
char *cp;
int ret = 0;
// decide if stdin is:
// (1) a TTY
// (2) a [redirected] file (e.g. invoked with ./myprogram < input)
static int echoflg = -1;
if (echoflg < 0) {
struct termios tio;
echoflg = (tcgetattr(fileno(stdin),&tio) < 0);
}
// NOTE: usage of the error codes in errno.h is arbitrary
while (ret <= 0) {
// ensure buffer has enough space
if (buflen < 2) {
ret = -ENOMEM;
break;
}
// output prompt
printf("%s: ",prompt);
fflush(stdout);
// get a line
cp = fgets(buf,buflen,stdin);
// EOF
if (cp == NULL) {
ret = -ENODATA;
break;
}
// echo file input to simulate TTY input
if (echoflg)
fputs(buf,stdout);
// get buffer length
ret = strlen(buf);
// empty string
if (ret <= 0)
continue;
// point to last char
cp = &buf[ret - 1];
// ensure we got a newline -- if not, fgets had to chop the line (i.e.)
// the line is too long to fit in the buffer
if (*cp != '\n') {
ret = -ENOSPC;
break;
}
// strip the newline -- we are done
*cp = 0;
--ret;
}
return ret;
}
// getnum_strtol -- get number using strtol
long
getnum_strtol(const char *prompt)
{
int len;
int readflg = 1;
char *cp;
char buf[100];
long num = 0;
while (readflg) {
len = getstr(buf,sizeof(buf),prompt);
if (len < 0)
exit(1);
num = strtol(buf,&cp,10);
// ensure we got a least one digit
if (cp <= buf)
continue;
switch (*cp) {
case ' ':
case '\t':
case 0:
readflg = 0;
break;
default:
printf("getnum_strtol: not a valid number -- buffer '%s', invalid '%s'\n",
buf,cp);
break;
}
}
return num;
}
// getnum_manual -- get number _not_ using strtol
long
getnum_manual(const char *prompt)
{
int len;
int readflg = 1;
int sign = 0;
int valid;
int chr;
char *cp;
char buf[100];
long num = 0;
while (readflg) {
len = getstr(buf,sizeof(buf),prompt);
// fatal error
if (len < 0)
exit(1);
// point to buffer start
cp = buf;
// find first non-whitespace character
valid = 0;
while (1) {
chr = *cp;
// end of string
if (chr == 0)
break;
// found character
valid = ((chr != ' ') && (chr != '\t'));
if (valid)
break;
++cp;
}
if (!valid)
continue;
// reset the accumlated number and the sign
num = 0;
sign = 0;
valid = 0;
// loop through all characters in buffer
while (1) {
chr = *cp++;
// get the sign of the number (and skip an explicit sign)
if (sign == 0) {
switch (chr) {
case '+':
sign = 1;
chr = *cp++;
break;
case '-':
sign = -1;
chr = *cp++;
break;
default:
sign = 1;
break;
}
}
// stop decoding number on whitespace
switch (chr) {
case ' ':
case '\t':
chr = 0;
break;
}
// check for clean end of number
if (chr == 0) {
if (valid) {
readflg = 0;
break;
}
}
// not a valid digit
if (!isdigit((unsigned char) chr)) {
cp -= 1;
printf("getnum_manual: not a valid number -- buffer '%s', invalid '%s'\n",
buf,cp);
break;
}
// add digit to number
num *= 10;
chr -= '0';
num += chr;
// we got at least one valid digit
valid = 1;
}
}
// apply sign
num *= sign;
return num;
}
在上面的代码中,我使用了cpp
个条件来表示旧代码和新代码:
#if 0
// old code
#else
// new code
#endif
#if 1
// new code
#endif
注意:这可以通过运行文件到unifdef -k
下面是我使用的程序输入文件:
5
45
0
90
5
70
8
38
15
55
20
10
以下是程序输出:
CPU scheduling method: Round Robin (RR)
Enter the number of processes: 5
Enter Burst Time for process 1: 45
Enter Arrival Time for process 1: 0
Enter Burst Time for process 2: 90
Enter Arrival Time for process 2: 5
Enter Burst Time for process 3: 70
Enter Arrival Time for process 3: 8
Enter Burst Time for process 4: 38
Enter Arrival Time for process 4: 15
Enter Burst Time for process 5: 55
Enter Arrival Time for process 5: 20
Enter the size of time slice: 10
------------------------------ INITIAL CONDITIONS ------------------------------
P(i) Arrival Burst Finish Turn Wait Resp Remain Give Round Clock
Time Time Time Around Time Time Time Range
0 0 45 0 0 0 0 45 0 0 0--1
1 5 90 0 0 0 0 90 0 1 0--1
2 8 70 0 0 0 0 70 0 2 0--1
3 15 38 0 0 0 0 38 0 3 0--1
4 20 55 0 0 0 0 55 0 4 0--1
-------------------------------- HISTORY/GANTT ---------------------------------
P(i) Arrival Burst Finish Turn Wait Resp Remain Give Round Clock
Time Time Time Around Time Time Time Range
0 0 45 0 0 0 0 35 10 0 0-9
1 5 90 0 0 0 10 80 10 1 10-19
2 8 70 0 0 0 20 60 10 2 20-29
3 15 38 0 0 0 30 28 10 3 30-39
4 20 55 0 0 0 40 45 10 4 40-49
P(i) Arrival Burst Finish Turn Wait Resp Remain Give Round Clock
Time Time Time Around Time Time Time Range
0 0 45 0 0 0 50 25 10 5 50-59
1 5 90 0 0 0 10 70 10 6 60-69
2 8 70 0 0 0 20 50 10 7 70-79
3 15 38 0 0 0 30 18 10 8 80-89
4 20 55 0 0 0 40 35 10 9 90-99
P(i) Arrival Burst Finish Turn Wait Resp Remain Give Round Clock
Time Time Time Around Time Time Time Range
0 0 45 0 0 0 50 15 10 10 100-109
1 5 90 0 0 0 10 60 10 11 110-119
2 8 70 0 0 0 20 40 10 12 120-129
3 15 38 0 0 0 30 8 10 13 130-139
4 20 55 0 0 0 40 25 10 14 140-149
P(i) Arrival Burst Finish Turn Wait Resp Remain Give Round Clock
Time Time Time Around Time Time Time Range
0 0 45 0 0 0 50 5 10 15 150-159
1 5 90 0 0 0 10 50 10 16 160-169
2 8 70 0 0 0 20 30 10 17 170-179
3 15 38 188 173 150 30 0 8 18 180-187
4 20 55 0 0 0 40 15 10 19 188-197
P(i) Arrival Burst Finish Turn Wait Resp Remain Give Round Clock
Time Time Time Around Time Time Time Range
0 0 45 203 203 158 50 0 5 20 198-202
1 5 90 0 0 0 10 40 10 21 203-212
2 8 70 0 0 0 20 20 10 22 213-222
4 20 55 0 0 0 40 5 10 23 223-232
1 5 90 0 0 0 10 30 10 24 233-242
P(i) Arrival Burst Finish Turn Wait Resp Remain Give Round Clock
Time Time Time Around Time Time Time Range
2 8 70 0 0 0 20 10 10 25 243-252
4 20 55 258 238 203 40 0 5 26 253-257
1 5 90 0 0 0 10 20 10 27 258-267
2 8 70 278 270 208 20 0 10 28 268-277
1 5 90 0 0 0 10 10 10 29 278-287
P(i) Arrival Burst Finish Turn Wait Resp Remain Give Round Clock
Time Time Time Around Time Time Time Range
1 5 90 298 293 208 10 0 10 30 288-297
------------------------------------ FINAL -------------------------------------
P(i) Arrival Burst Finish Turn Wait Resp Remain Give Round Clock
Time Time Time Around Time Time Time Range
0 0 45 203 203 158 50 0 5 31 288-297
1 5 90 298 293 208 10 0 10 32 288-297
2 8 70 278 270 208 20 0 10 33 288-297
3 15 38 188 173 150 30 0 8 34 288-297
4 20 55 258 238 203 40 0 5 35 288-297
0 0 0 0 1177 927 150 0 0 36 288-297
Average Waiting Time: 185.4
Average Turnaround Time: 235.4
Average Response Time: 30.0