CSCI4210-无代写
时间:2024-04-04
CSCI 4210 — Operating Systems
Simulation Project Part II (document version 1.0)
Processes and CPU Scheduling
Overview
• This assignment is due in Submitty by 11:59PM EST on Wednesday, April 3, 2024
• This project is to be completed either individually or in a team of at most two students; teams
are formed in the Submitty gradeable, but do not submit any code until we announce that
auto-grading is available
• Note that you can change teams from Part I to Part II
• Beyond your team (or yourself if working alone), do not share your code; however, feel free
to discuss the project content and your findings with one another on our Discussion Forum
• To appease Submitty, you must use one of the following programming languages: C, C++,
Java, or Python (be sure you choose only one language for your entire implementation)
• You will have 16 penalty-free submissions, after which a small penalty will be applied
• You can use at most three late days on this assignment; in such cases, each team member
must use a late day
• Given that your simulation results might not entirely match the expected output on Submitty,
we will cap your auto-graded grade at 50 points even though there will be more than 50
auto-graded points available in Submitty; this should help you avoid the need to handle
unusual corner cases, which are not an important aspect of this project
• All submitted code must successfully compile and run on Submitty.
• If you use C or C++, your program must successfully compile via gcc or g++ with no warning
messages when the -Wall (i.e., warn all) compiler option is used; we will also use -Werror,
which will treat all warnings as critical errors; the -lm flag will also be included.
• For source file naming conventions, be sure to use *.c for C and *.cpp for C++; in either
case, you can also include *.h files
• If you use Java, name your main Java file Project.java, do not use the package directive
• For Python, you must use python3; be sure to name your main Python file project.py
• For Java and Python, be sure no warning messages or extraneous output occur during com-
pilation/interpretation
• Please “flatten” all directory structures to a single directory of source files before submitting
your code
2
Project specifications
For Part II of our simulation project, you will simulate an operating system given the set of processes
pseudo-randomly generated in Part I. The overall focus will again be on processes, assumed to be
resident in memory, waiting to use the CPU. Memory and the I/O subsystem will not be covered
in depth in either part of this project.
Conceptual design — (from Part I)
A process is defined as a program in execution. For this assignment, processes are in one of the
following three states, corresponding to the picture shown further below.
• RUNNING: actively using the CPU and executing instructions
• READY: ready to use the CPU, i.e., ready to execute a CPU burst
• WAITING: blocked on I/O or some other event
RUNNING
STATE
READY
STATE
WAITING (on I/O)
STATE
+-----+ +---------------------+
| | +-------------------+ | |
| CPU | <== | | | | | | I/O Subsystem |
| | +-------------------+ | |
+-----+ <<< queue <<<<<<<<< + ------------------------------- +
Processes in the READY state reside in a queue called the ready queue. This queue is ordered
based on a configurable CPU scheduling algorithm. You will implement specific CPU scheduling
algorithms in Part II of this project.
All implemented algorithms (in Part II) will be simulated for the same set of processes, which
will therefore support a comparative analysis of results. In Part I, the focus is on generating useful
sets of processes via pseudo-random number generators.
Back to the conceptual model, when a process is in the READY state and reaches the front of the
queue, once the CPU is free to accept the next process, the given process enters the RUNNING
state and starts executing its CPU burst.
After each CPU burst is completed, if the process does not terminate, the process enters the
WAITING state, waiting for an I/O operation to complete (e.g., waiting for data to be read
in from a file). When the I/O operation completes, depending on the scheduling algorithm, the
process either (1) returns to the READY state and is added to the ready queue or (2) preempts
the currently running process and switches into the RUNNING state.
Note that preemptions occur only for certain algorithms.
3
Algorithms — (Part II)
The four algorithms that you must simulate are first-come-first-served (FCFS); shortest job first
(SJF); shortest remaining time (SRT); and round robin (RR). When you run your program, all
four algorithms are to be simulated in succession with the same set of processes.
Each algorithm is summarized below.
First-come-first-served (FCFS)
The FCFS algorithm is a non-preemptive algorithm in which processes simply line up in the ready
queue, waiting to use the CPU. This is your baseline algorithm.
Shortest job first (SJF)
In SJF, processes are stored in the ready queue in order of priority based on their anticipated CPU
burst times. More specifically, the process with the shortest predicted CPU burst time will be
selected as the next process executed by the CPU.
Shortest remaining time (SRT)
The SRT algorithm is a preemptive version of the SJF algorithm. In SRT, when a process arrives,
if it has a predicted CPU burst time that is less than the remaining predicted time of the currently
running process, a preemption occurs. When such a preemption occurs, the currently running
process is simply added to the ready queue.
Round robin (RR)
The RR algorithm is essentially the FCFS algorithm with time slice tslice. Each process is given
tslice amount of time to complete its CPU burst. If the time slice expires, the process is preempted
and added to the end of the ready queue.
If a process completes its CPU burst before a time slice expiration, the next process on the ready
queue is context-switched in to use the CPU.
For your simulation, if a preemption occurs and there are no other processes on the ready queue,
do not perform a context switch. For example, given process G is using the CPU and the ready
queue is empty, if process G is preempted by a time slice expiration, do not context-switch process G
back to the empty queue; instead, keep process G running with the CPU and do not count this as
a context switch. In other words, when the time slice expires, check the queue to determine if a
context switch should occur.
4
λ
2
λ
Simulation configuration — (extended from Part I)
The key to designing a useful simulation is to provide a number of configurable parameters. This
allows you to simulate and tune for a variety of scenarios, e.g., a large number of CPU-bound
processes, differing average process interarrival times, multiple CPUs, etc.
Define the simulation parameters shown below as tunable constants within your code, all of which
will be given as command-line arguments. In Part II of the project, additional parameters will be
added.
• argv[1]: Define n as the number of processes to simulate. Process IDs are assigned in
alphabetical order A through Z. Therefore, you will have at most 26 processes to simulate.
• argv[2]: Define ncpu as the number of processes that are CPU-bound. For this project, we
will classify processes as I/O-bound or CPU-bound. The ncpu CPU-bound processes, when
generated, will have CPU burst times that are longer by a factor of 4 and will have I/O burst
times that are shorter by a factor of 8.
• argv[3]: We will use a pseudo-random number generator to determine the interarrival times
of CPU bursts. This command-line argument, i.e. seed, serves as the seed for the pseudo-
random number sequence. To ensure predictability and repeatability, use srand48() with
this given seed before simulating each scheduling algorithm and drand48() to obtain the
next value in the range [0.0, 1.0). For languages that do not have these functions, implement
an equivalent 48-bit linear congruential generator, as described in the man page for these
functions in C.1
• argv[4]: To determine interarrival times, we will use an exponential distribution; therefore,
this command-line argument is parameter λ. Remember that 1 will be the average random
value generated, e.g., if λ = 0.01, then the average should be appoximately 100. See the
exp-random.c example; and use the formula shown in the code, i.e., -log( r ) / lambda,
where log is the natural logarithm.
• argv[5]: For the exponential distribution, this command-line argument represents the upper
bound for valid pseudo-random numbers. This threshold is used to avoid values far down the
long tail of the exponential distribution. As an example, if this is set to 3000, all generated
values above 3000 should be skipped. For cases in which this value is used in the ceiling
function (see the next page), be sure the ceiling is still valid according to this upper bound.
• argv[6]: Define tcs as the time, in milliseconds, that it takes to perform a context switch.
Specifically, the first half of the context switch time (i.e., tcs ) is the time required to remove
the given process from the CPU; the second half of the context switch time is the time
required to bring the next process in to use the CPU. Therefore, expect tcs to be a positive
even integer.
• argv[7]: For the SJF and SRT algorithms, since we cannot know the actual CPU burst
times beforehand, we will rely on estimates determined via exponential averaging. As such,
this command-line argument is the constant α. Note that the initial guess for each process
is τ0 = 1 . When calculating τ values, use the “ceiling” function for all calculations.
• argv[8]: For the RR algorithm, define the time slice value, tslice, measured in milliseconds.


1Feel free to post your code for this on the Discussion Forum for others to use.
5
Pseudo-random numbers and predictability — (from Part I)

A key aspect of this assignment is to compare the results of each of the simulated algorithms with
one another given the same initial conditions, i.e., the same initial set of processes.
To ensure each CPU scheduling algorithm runs with the same set of processes, carefully follow the
algorithm below to create the set of processes.
Define your exponential distribution pseudo-random number generation function as next_exp().
Then, for each of the n processes, in order A through Z, perform the steps below, with CPU-bound
processes generated last. Note that all generated values are integers.

1. Identify the initial process arrival time as the “floor” of the next random number in the
sequence given by next_exp(); note that you could therefore have a zero arrival time
2. Identify the number of CPU bursts for the given process as the “ceiling” of the next random
number generated from the uniform distribution (i.e., obtained via drand48()) multiplied
by 64; this should obtain a random integer in the inclusive range [1, 64]
3. For each of these CPU bursts, identify the CPU burst time and the I/O burst time as the
“ceiling” of the next two random numbers in the sequence given by next_exp(); multiply the
I/O burst time by 10 such that I/O burst time is generally an order of magnitude longer than
CPU burst time; for CPU-bound processes, multiply the CPU burst time by 4 and divide the
I/O burst time by 8; for the last CPU burst, do not generate an I/O burst time (since each
process ends with a final CPU burst)
6
Simulation specifics — (Part II)

After you simulate each scheduling algorithm, you must reset your simulation back to the initial
set of processes and set your elapsed time back to zero.
Note that there may be times during your simulation in which the simulated CPU is idle because
no processes have arrived yet or all processes are busy performing I/O. Also, your simulation ends
when all processes terminate.
If different types of events occur at the same time, simulate these events in the following order:
(a) CPU burst completion; (b) process starts using the CPU; (c) I/O burst completions; and
(d) new process arrivals.
Further, any “ties” that occur within one of these categories are to be broken using process ID
order. As an example, if processes G and S happen to both finish with their I/O at the same time,
process G wins this “tie” (because G is alphabetically before S) and is therefore added to the ready
queue before process S.
Be sure you do not implement any additional logic for the I/O subsystem. In other words, there
are no I/O queues to implement.
Your simulator should keep track of elapsed time t (measured in milliseconds), which is initially
zero for each scheduling algorithm. As your simulation proceeds, t advances to each “interesting”
event that occurs, displaying a specific line of output that describes each event.
The “interesting” events are:

• Start of simulation
• Process arrival (i.e., initially and at I/O completions)
• Process starts using the CPU
• Process finishes using the CPU (i.e., completes a CPU burst)
• Process has its τ value recalculated (i.e., after a CPU burst completion)
• Process preemption
• Process starts performing I/O
• Process finishes performing I/O
• Process terminates by finishing its last CPU burst
• End of simulation

The “process arrival” event occurs every time a process arrives, which includes both the initial
arrival time and when a process completes an I/O burst. In other words, processes “arrive” within
the subsystem that consists only of the CPU and the ready queue.
The “process preemption” event occurs each time a process is preempted. When a preemption
occurs, a context switch occurs, except for the RR algorithm when the ready queue is empty.
7
Measurements — (from Part I)

There are a number of measurements you will want to track in your simulation. For each algorithm,
you will count the number of preemptions and the number of context switches that occur. Further,
you will measure CPU utilization by tracking CPU usage and CPU idle time.
Specifically, for each CPU burst, you will measure CPU burst time (given), turnaround time,
and wait time.


CPU burst time

CPU burst times are randomly generated for each process that you simulate via the above algorithm.
CPU burst time is defined as the amount of time a process is actually using the CPU. Therefore,
this measure does not include context switch times.


Turnaround time

Turnaround times are to be measured for each process that you simulate. Turnaround time is
defined as the end-to-end time a process spends in executing a single CPU burst.
More specifically, this is measured from process arrival time through to when the CPU burst is
completed and the process is switched out of the CPU. Therefore, this measure includes the second
half of the initial context switch in and the first half of the final context switch out, as well as any
other context switches that occur while the CPU burst is being completed (i.e., due to preemptions).


Wait time

Wait times are to be measured for each CPU burst. Wait time is defined as the amount of time
a process spends waiting to use the CPU, which equates to the amount of time the given process
is actually in the ready queue. Therefore, this measure does not include context switch times that
the given process experiences, i.e., only measure the time the given process is actually in the ready
queue.


CPU utilization

Calculate CPU utilization by tracking how much time the CPU is actively running CPU bursts
versus total elapsed simulation time.
8
Required terminal output — (Part II)

For Part II, required terminal output shows abbreviated Part I output followed by output for each
of the four simulated algorithms.
Your simulator must display results for each of the four algorithms you simulate. For each algorithm,
display a summary for each “interesting” event that occurs from time 0 through time 9999. For
time 10000 and beyond, only display process termination events and the final end-of-simulation
event. Example output files have been posted to Submitty.
Your simulator must display a line of output for each “interesting” event that occurs using the
format shown below. Note that the contents of the ready queue are shown for each event.
time ms: [Q ]
The output format must follow the example shown below.
bash$ ./a.out 3 1 1024 0.001 3000 4 0.75 256
<<< PROJECT PART I -- process set (n=3) with 1 CPU-bound process >>>
I/O-bound process A: arrival time 136ms; 17 CPU bursts
I/O-bound process B: arrival time 929ms; 12 CPU bursts
CPU-bound process C: arrival time 26ms; 60 CPU bursts

<<< PROJECT PART II -- t_cs=4ms; alpha=0.75; t_slice=256ms >>>
time 0ms: Simulator started for FCFS [Q ]
time 26ms: Process C arrived; added to ready queue [Q C]
time 28ms: Process C started using the CPU for 2920ms burst [Q ]
time 136ms: Process A arrived; added to ready queue [Q A]
time 929ms: Process B arrived; added to ready queue [Q A B]
time 2948ms: Process C completed a CPU burst; 59 bursts to go [Q A B]
time 2948ms: Process C switching out of CPU; blocking on I/O until time 3318ms [Q A B]
time 2952ms: Process A started using the CPU for 1330ms burst [Q B]
time 3318ms: Process C completed I/O; added to ready queue [Q B C]
time 4282ms: Process A completed a CPU burst; 16 bursts to go [Q B C]
time 4282ms: Process A switching out of CPU; blocking on I/O until time 10024ms [Q B C]
time 4286ms: Process B started using the CPU for 2438ms burst [Q C]
time 6724ms: Process B completed a CPU burst; 11 bursts to go [Q C]
time 6724ms: Process B switching out of CPU; blocking on I/O until time 7606ms [Q C]
time 6728ms: Process C started using the CPU for 2328ms burst [Q ]
time 7606ms: Process B completed I/O; added to ready queue [Q B]
time 9056ms: Process C completed a CPU burst; 58 bursts to go [Q B]
time 9056ms: Process C switching out of CPU; blocking on I/O until time 12170ms [Q B]
time 9060ms: Process B started using the CPU for 1173ms burst [Q ]
time 155555ms: Process A terminated [Q ]
time 180527ms: Process B terminated [Q ]
time 324061ms: Process C terminated [Q ]
time 324063ms: Simulator ended for FCFS [Q ]
9
time 0ms: Simulator started for SJF [Q ]
time 26ms: Process C (tau 1000ms) arrived; added to ready queue [Q C]
time 28ms: Process C (tau 1000ms) started using the CPU for 2920ms burst [Q ]
time 136ms: Process A (tau 1000ms) arrived; added to ready queue [Q A]
time 929ms: Process B (tau 1000ms) arrived; added to ready queue [Q A B]
time 2948ms: Process C (tau 1000ms) completed a CPU burst; 59 bursts to go [Q A B]
time 2948ms: Recalculating tau for process C: old tau 1000ms ==> new tau 2440ms [Q A B]
time 2948ms: Process C switching out of CPU; blocking on I/O until time 3318ms [Q A B]
time 2952ms: Process A (tau 1000ms) started using the CPU for 1330ms burst [Q B]
time 3318ms: Process C (tau 2440ms) completed I/O; added to ready queue [Q B C]
time 4282ms: Process A (tau 1000ms) completed a CPU burst; 16 bursts to go [Q B C]
time 4282ms: Recalculating tau for process A: old tau 1000ms ==> new tau 1248ms [Q B C]
time 4282ms: Process A switching out of CPU; blocking on I/O until time 10024ms [Q B C]
time 4286ms: Process B (tau 1000ms) started using the CPU for 2438ms burst [Q C]
time 6724ms: Process B (tau 1000ms) completed a CPU burst; 11 bursts to go [Q C]
time 6724ms: Recalculating tau for process B: old tau 1000ms ==> new tau 2079ms [Q C]
time 6724ms: Process B switching out of CPU; blocking on I/O until time 7606ms [Q C]
time 6728ms: Process C (tau 2440ms) started using the CPU for 2328ms burst [Q ]
time 7606ms: Process B (tau 2079ms) completed I/O; added to ready queue [Q B]
time 9056ms: Process C (tau 2440ms) completed a CPU burst; 58 bursts to go [Q B]
time 9056ms: Recalculating tau for process C: old tau 2440ms ==> new tau 2356ms [Q B]
time 9056ms: Process C switching out of CPU; blocking on I/O until time 12170ms [Q B]
time 9060ms: Process B (tau 2079ms) started using the CPU for 1173ms burst [Q ]
time 156293ms: Process A terminated [Q ]
time 181265ms: Process B terminated [Q ]
time 324799ms: Process C terminated [Q ]
time 324801ms: Simulator ended for SJF [Q ]

time 0ms: Simulator started for SRT [Q ]
time 26ms: Process C (tau 1000ms) arrived; added to ready queue [Q C]
time 28ms: Process C (tau 1000ms) started using the CPU for 2920ms burst [Q ]
time 136ms: Process A (tau 1000ms) arrived; added to ready queue [Q A]
time 929ms: Process B (tau 1000ms) arrived; added to ready queue [Q A B]
time 2948ms: Process C (tau 1000ms) completed a CPU burst; 59 bursts to go [Q A B]
time 2948ms: Recalculating tau for process C: old tau 1000ms ==> new tau 2440ms [Q A B]
time 2948ms: Process C switching out of CPU; blocking on I/O until time 3318ms [Q A B]
time 2952ms: Process A (tau 1000ms) started using the CPU for 1330ms burst [Q B]
time 3318ms: Process C (tau 2440ms) completed I/O; added to ready queue [Q B C]
time 4282ms: Process A (tau 1000ms) completed a CPU burst; 16 bursts to go [Q B C]
time 4282ms: Recalculating tau for process A: old tau 1000ms ==> new tau 1248ms [Q B C]
time 4282ms: Process A switching out of CPU; blocking on I/O until time 10024ms [Q B C]
time 4286ms: Process B (tau 1000ms) started using the CPU for 2438ms burst [Q C]
time 6724ms: Process B (tau 1000ms) completed a CPU burst; 11 bursts to go [Q C]
time 6724ms: Recalculating tau for process B: old tau 1000ms ==> new tau 2079ms [Q C]
time 6724ms: Process B switching out of CPU; blocking on I/O until time 7606ms [Q C]
time 6728ms: Process C (tau 2440ms) started using the CPU for 2328ms burst [Q ]
time 7606ms: Process B (tau 2079ms) completed I/O; added to ready queue [Q B]
time 9056ms: Process C (tau 2440ms) completed a CPU burst; 58 bursts to go [Q B]
10
time 9056ms: Recalculating tau for process C: old tau 2440ms ==> new tau 2356ms [Q B]
time 9056ms: Process C switching out of CPU; blocking on I/O until time 12170ms [Q B]
time 9060ms: Process B (tau 2079ms) started using the CPU for 1173ms burst [Q ]
time 130658ms: Process A terminated [Q C]
time 179922ms: Process B terminated [Q C]
time 328512ms: Process C terminated [Q ]
time 328514ms: Simulator ended for SRT [Q ]

time 0ms: Simulator started for RR [Q ]
time 26ms: Process C arrived; added to ready queue [Q C]
time 28ms: Process C started using the CPU for 2920ms burst [Q ]
time 136ms: Process A arrived; added to ready queue [Q A]
time 284ms: Time slice expired; preempting process C with 2664ms remaining [Q A]
time 288ms: Process A started using the CPU for 1330ms burst [Q C]
time 544ms: Time slice expired; preempting process A with 1074ms remaining [Q C]
time 548ms: Process C started using the CPU for remaining 2664ms of 2920ms burst [Q A]
time 804ms: Time slice expired; preempting process C with 2408ms remaining [Q A]
time 808ms: Process A started using the CPU for remaining 1074ms of 1330ms burst [Q C]
time 929ms: Process B arrived; added to ready queue [Q C B]
time 1064ms: Time slice expired; preempting process A with 818ms remaining [Q C B]
time 1068ms: Process C started using the CPU for remaining 2408ms of 2920ms burst [Q B A]
time 1324ms: Time slice expired; preempting process C with 2152ms remaining [Q B A]
time 1328ms: Process B started using the CPU for 2438ms burst [Q A C]
time 1584ms: Time slice expired; preempting process B with 2182ms remaining [Q A C]
time 1588ms: Process A started using the CPU for remaining 818ms of 1330ms burst [Q C B]
time 1844ms: Time slice expired; preempting process A with 562ms remaining [Q C B]
...
time 7056ms: Process C completed I/O; added to ready queue [Q C]
time 7058ms: Process C started using the CPU for 2328ms burst [Q ]
time 7314ms: Time slice expired; no preemption because ready queue is empty [Q ]
time 7570ms: Time slice expired; no preemption because ready queue is empty [Q ]
time 7706ms: Process B completed I/O; added to ready queue [Q B]
time 7826ms: Time slice expired; preempting process C with 1560ms remaining [Q B]
time 7830ms: Process B started using the CPU for 1173ms burst [Q C]
time 8086ms: Time slice expired; preempting process B with 917ms remaining [Q C]
...
time 132593ms: Process A terminated [Q C]
time 175973ms: Process B terminated [Q C]
time 335272ms: Process C terminated [Q ]
time 335274ms: Simulator ended for RR [Q ]
11
Required output file — (Part II)

In addition to the above output, which is sent to stdout, generate an output file called simout.txt
that contains statistics for each simulated algorithm.
The file format is shown below. Use the “ceiling” function out to exactly three digits after the
decimal point for your averages.
Note the values in parentheses show the data specifically for CPU-bound and I/O-bound processes,
respectively.
If calculating the average will cause division by 0, simply set the average to 0.
bash$ ./a.out 3 1 1024 0.001 3000 4 0.75 256
...
bash$ cat simout.txt
Algorithm FCFS
-- CPU utilization: 84.253%
-- average CPU burst time: 3067.776 ms (4071.000 ms/992.138 ms)
-- average wait time: 779.663 ms (217.284 ms/1943.207 ms)
-- average turnaround time: 3851.439 ms (4292.284 ms/2939.345 ms)
-- number of context switches: 89 (60/29)
-- number of preemptions: 0 (0/0)
Algorithm SJF
-- CPU utilization: 84.062%
-- average CPU burst time: 3067.776 ms (4071.000 ms/992.138 ms)
-- average wait time: 804.540 ms (229.584 ms/1994.104 ms)
-- average turnaround time: 3876.315 ms (4304.584 ms/2990.242 ms)
-- number of context switches: 89 (60/29)
-- number of preemptions: 0 (0/0)
Algorithm SRT
-- CPU utilization: 83.112%
-- average CPU burst time: 3067.776 ms (4071.000 ms/992.138 ms)
-- average wait time: 542.686 ms (290.800 ms/1063.828 ms)
-- average turnaround time: 3614.911 ms (4366.467 ms/2059.966 ms)
-- number of context switches: 99 (70/29)
-- number of preemptions: 10 (10/0)

Algorithm RR
-- CPU utilization: 81.436%
-- average CPU burst time: 3067.776 ms (4071.000 ms/992.138 ms)
-- average wait time: 588.686 ms (398.067 ms/983.069 ms)
-- average turnaround time: 3668.236 ms (4479.134 ms/1990.518 ms)
-- number of context switches: 262 (151/111)
-- number of preemptions: 173 (91/82)
12
Error handling — (from Part I)

If improper command-line arguments are given, report an error message to stderr and abort
further program execution. In general, if an error is encountered, display a meaningful error
message on stderr, then abort further program execution.
Error messages must be one line only and use the following format:

ERROR:


Submission instructions — (from Part I)

To submit your assignment and also perform final testing of your code, please use Submitty.
Note that this assignment will be available on Submitty a minimum of three days before the due
date. Please do not ask when Submitty will be available, as you should first perform adequate
testing on your own Ubuntu platform.

Relinquishing allocated resources — (from Part I)

Be sure that all resources (e.g., dynamically allocated memory) are properly relinquished for what-
ever language/platform you use for this assignment. Sloppy programming will likely result in lower
grades. Consider doing frequent code reviews with your teammates if working on a team.
13
Analysis questions to think about — (Part II)

As you work on this project, consider the questions below. Though there is no formal write-up
required for this project, you should be able to answer at least some of these questions based on
specific results from your simulation. A few of these questions would require features beyond the
given requirements.

1. Of the four simulated algorithms, which algorithm is the “best” algorithm for CPU-bound
processes? Which algorithm is best-suited for I/O-bound processes?
2. For the SJF and SRT algorithms, what value of α produced the “best” results?
3. For the SJF and SRT algorithms, how does changing from a non-preemptive algorithm to a
preemptive algorithm impact your results? Are there specific examples of processes that have
improved turnaround or wait times?
4. Identify at least three limitations of your simulation, in particular how the project specifica-
tions could be expanded to better model a real-world operating system.
5. Identify other “interesting” events and measurements that you could incorporate into your
simulation.
6. Describe a priority scheduling algorithm of your own design, i.e., how could you calculate
priority? What are advantages and disadvantages of your algorithm?
Again, the above questions are included here for you to think about and discuss with your team-
mates and/or others in the course. Feel free to open a discussion about these on our Discussion
Forum.

essay、essay代写