We present a graphical simulation tool for visually and interactively exploring the processing of a variety of events handled by an operating system when running a program. Our tool graphically demonstrates a variety of concepts and processes of a preemptive, multi-tasking operating systems (os), including scheduling algorithms, i/o processing, interrupts, context switches, task structures, and semaphore processing .
Our graphical tool was designed to run on top of a solution to a text-based course programming project—here after referred to as the underlying simulation engine—in which students design and implement a program that simulates some of the job and cpu scheduling, and semaphore processing of a time-shared operating system. The complete project specification for the underlying simulation engine is available online at http://perugini.cps.udayton.edu/teaching/courses/Fall2018/cps356/#midterm. The architectural view of the underling simulation engine, which also serves to convey some of the project/system requirements, is shown in Figure 1.
While demonstrating os concepts using physical computer hardware and real operating systems is effective, a software simulation is less expensive to develop and more configurable. For instance, users of our tool have control over both the time-based events and the parameters of the system (e.g., quantum size, scheduling algorithm, memory constraints) that are uncontrollable/unpredictable at the user level in a real computing system. Moreover, a visual simulation graphically reveals the internal processing of and event handling within an os from which the user is typically shielded. The ability to step through the handling of certain events (e.g., new process creation, process termination, i/o completion, context switch) enabled by our tool in user-defined increments of cpu time is formative in students’ conceptualization, comprehension, and visualization these complex processes at work within an os.
The graphical simulation tool is implemented using the React library for the fancy ui elements of the Node.js framework and is available as a web application at https://cpudemo.azurewebsites.net/#/simulator. Our graphical simulator is available for use on the web by both instructors and students for purposes of pedagogy. Instructors can use it to for live demonstrations of course concepts in class, while students can use it outside of class to explore the concepts. Assigning the development of the underling text-based simulation engine, on which the graphical simulator runs, to students as a course project is also an effective approach to teach students the concepts—more on this below.
2 Simulation Details
The tool, shown in Figure 2, contains an incoming event queue, shown at the top of the left-most column of the tool, which lists all events in the current session. Below the event queue is a process control block (pcb). The middle columns of the tool contain the multi-level, fifo ready queue, the i/o wait queue, and the semaphore wait queues. These queues are all limited in size by the available main memory, displayed in the upper right corner of the tool. The right-most column of the tool contains a block representing the cpu, and a table of the completed jobs. The user can step through events in multiple ways. The top of the tool shows the current simulation time, which the user can modify at any time. Alternatively, there are controls to allow the user to step through the simulation by a chosen number of cpu time increments—the default is 1 or 100 units. Finally, there is a button that will show or hide the semaphore waiting queues and make the other queues display larger, as shown in the screen in Figure 3.
The screen in Figure 2 shows the system before any events occur. In the right screen, 100 units of time have elapsed and the first event occurs—a new job arrival—identified by the letter ‘A’ in the first column of each table. Note that the job id, and runtime and memory requirements are also provided. The new job immediately moves into the job queue, which triggers the job scheduling algorithm. Since job 1 requires 20 units of memory, and 512 units are available, job 1 is immediately loaded into the first level of the ready queue. Since the cpu is idle up to this point, the arrival of a job in the ready queue triggers the cpu scheduling algorithm, which moves job 1 from the ready queue and onto the cpu with a quantum of 100 units of time. While this simulation does not currently factor in the overhead context switch time (i.e., time required to move jobs between the various queues and the cpu, job 1 does not run until the next clock cycle of the cpu. A summary of time stamp 100 is that the first job appeared, was instantaneously loaded onto the cpu (through the job queue and first-level ready queue). At time 101, shown in Figure 5, job 1 will run for 1 unit of the 78 required units of time before completion and will have a remaining quantum of 99 clock cycles remaining.
In the screen in Figure 6, the simulation has been running to time 119. Job 1 has run for a total of 19 units of time, and requires 59 additional units of time until completion. Since the remaining quantum for job 1 is 81 units of time, the job could finish without time-slicing, unless job 1 requires i/o in the interim. During the next unit of time, shown in the screen in Figure 7, a new job arrives. It is moved into the job queue, which triggers the job scheduling algorithm. Since job 2 requires 60 units of memory, and there are 492 units available, job 2 is immediately loaded into the first level of the ready queue. Since the cpu is busy with job1 at this point in time, job 2 must wait in the ready queue. In the lower-middle screen, the current time is now 130 and two additional (new) jobs have been loaded into the ready queue. At time 131, there is an event for the arrival of a new job (job 5). However, job 5 requires 513 units of memory, which is greater than the 512 units of memory of total memory that the simulation supports. In this simulation, since there is not enough memory to accommodate job 5, it can never run and is rejected in an alert message shown in the upper-right screen. This presents an opportunity to mention to students that in a virtual memory management scheme—a forth-coming topic—this job would be runnable, even though it exceeds the cumulative amount of system memory.
At time 136, a job will arrive that requires exactly 512 units of memory. While this job will enter the job queue, it will not be permitted to enter the ready queue until all unfinished jobs have fully completed (i.e., terminated) and been flushed out of the system and, thus, leaving the full 512 units of memory free. In the screen in Figure 10, the simulator is now at time 177 and job 1 requires only 1 unit of time before its completion. The screen in Figure 11 shows the result of running that job for 1 more unit of time. Observe that job 1 has moved to the finished job queue, and job 2 has been loaded onto the cpu and requires 90 units of time to complete.
Moving forward to time 779, shown in the screen in Figure 12, we see that several jobs have already finished, several are in the first level of the ready queue, and many jobs are waiting in the job queue. In the incoming event table, we see that the next event will occur at time 780 and is identified with the symbol ‘i’. An i event is a request for i/o by the current job on the cpu, in this case, job 13. At time 780, shown in the screen in Figure 13, job 13 is preempted from the cpu and moved to the i/o wait queue for the specified i/o burst. Once its i/o burst is complete, the job will be (demoted and) moved to the first level of the ready queue. Many other additional i/o events occur over the next few time increments.
Up to this point, the allotted quantum of 100 units has been sufficient for each jobs to finish before a quantum expiration. At time 1,569, shown in the screen in Figure 14, job 26 requires 2 units of time before completion, but its remaining quantum is 1 unit of time. In the screen in Figure 15, job 26 has been moved to the second level of the ready queue at time 1,570, and will not get back on the cpu again until the first level of the ready queue is empty. This job only required 1 more unit of time to complete, but must now wait (potentially indefinitely) for more time on the cpu. Students often raise questions about the efficiency of such a scheduling scheme. We take this time to discuss the tradeoffs of scheduling algorithms and potential solutions to starvation such as aging.
We now demonstrate the use of the system semaphores. The first semaphore event is a semaphore signal which is identified with by an ‘s.’ This signal occurs at time 7,068 and will signal semaphore 4. The availability of a semaphore is tracked next to the semaphore labels in the semaphore waiting queue tables. When a semaphore wait event, identified with a ‘w’, occurs, it causes the current job on the cpu to wait on the semaphore. If the semaphore is available, its value is decremented and the job remains on the cpu. If is the semaphore is unavailable (i.e., has a value of 0), the job will be moved to from the cpu to the corresponding semaphore wait queue until the semaphore is available (through a subsequent ‘s event). The first job to block waiting in a semaphore wait queue is job 57 at time 7,450 in semaphore wait queue 3. This is shown in the screen in Figure 16.
3 Student Feedback
Students across a wide range of offerings of the os course have found this project to develop the underlying simulation engine helpful for discerning and gaining an appreciation of the difficulty in the copious event processing an os must handle. It also gives them a feel for the operations management nature of an os.
The project really nailed in the main concepts of operating systems in general.
The project was also an interactive and engaging experience that demonstrated and explained concepts we were working on in class.
I found that the project really helped me learn how an operating system scheduler worked.
Also I found the project to be really fun, I actually enjoyed working on it.
…mostly the project that we did halfway through the semester was very beneficial to my learning looking back at it.
Students have used Python, Perl, Scheme, Java, and C++ to develop a solution to the underlying simulation engine project.
There are multiple extensions to the underlying simulation engine that can be assigned to students as follow-on projects. For instance, students can implement a memory management scheme (e.g., paging) to the organization of the ready queues and/or simulate a multi-core processor. Also, note that the underlying simulation engine is a single-threaded program, albeit one that simulates multiple parallel processes. Once students implement the single-threaded implementation, a possible segue into the topics of concurrency and synchronization might be to re-design/implement the simulator in a multi-threaded fashion using an event-based concurrency model such as the Actor model of concurrency in, e.g., Elixir.
We plan multiple enhancements to the graphical overly intended to make the tool more flexible to facilitate use by other educators. For instance, we plan to redesign the event queue so that it is editable enabling an instructor to create event sequences that demonstrate specific scenarios and event collisions at will. The web tool features a toggle that will add or remove the semaphore wait queues and corresponding events. Multiple event sequences are currently available that demonstrate many of the aspects of the simulation. We plan to release a series of online tutorials for usage of the tool.
Ultimately, we plan to decouple our graphical visualization from the underlying text-based simulator. This will allow an instructor to overlay our visualization on top of any operating system for which the instructor’s students are simulating. This will afford the instructor the freedom to customize the design requirements and parameters of the particular operating system the students are simulating while still being able to make use of the visualization for purposes of any of its pedagogical purposes. Moreover, this decoupling will enable students make use of the graphical overlay as a tool to debug their underlying simulation engine. Observing the operation of their underlying simulation graphically will help students identify bugs in their implementation more quickly than wading through pages of textual dumps of their systems queues, e.g., to identify a process that went awry.
This material is based upon work supported by the National Science Foundation under Grant Numbers 1712406 and 1712404. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation.
The source of the underlying simulation engine is a course project designed by John A. Lewis in which students design and implement a program that simulates some of the job and cpu scheduling, and semaphore processing of a time-shared operating system.
-  A. Silberschatz, P.B. Galvin, and G. Gagne. Operating system concepts. John Wiley and Sons, Inc., Hoboken, NJ, tenth edition, 2018.