Operating Systems Project, Spring 2012

Architecture Simulator


Table of Contents

Introduction

This page describes the software used to simulate the hardware architecture defined for the operating system project. You should be familiar with the hardware architecture before reading this page.

The hardware simulator code and your operating system code combine to form the simulation program. However, it’s easier to understand the simulation program if the hardware and operating system code are thought of as being separate parts of the simulation program. As with a real computing system, the connection between the hardware and the operating system occurs at the interrupt handlers.

Unlike a real computing system, however, the operating system in the simulation program does not run on the hardware it controls. The operating system executes as native Java code, while user processes execute on the simulated hardware. This may be a bit confusing at first, particularly for those that have written native operating systems, but this approach is much simpler than writing a native operating system, and the fundamental concepts used in each are the same.

The Project Directory

Files related to the simulator can be found under the /export/home/class/cs-os/pai project directory, where i is the assignment number (1, 2, 3, or 4). The project directory should be accessible from most Monmouth University machines.

The simulator jar contains all the code needed to build a simulator, including main(). To run the simulator, type

java -cp /export/home/class/cs-os/pai/pai-yymmdd.jar:. main yourOS batchDiskName
where i is the assignment number (1, 2, 3, or 4), yymmdd is the date for the most recent jar file, yourOS is the name of the class implementing the OperatingSystem interface, and batchDiskName is the name of a batch disk.

The simulator is written in Java version 6. The simulator jar should be backwards compatible with earlier versions of Java (I have not tested this), but upgrading to version 6 is a good idea.

Simulator Implementation Structure

The simulator comprises many classes, but five constituent classes are the most important. Four of the important classes correspond to the four pieces of the hardware architecture: CPU, Primary Store, Disk, and Terminal. The fifth class, the Hardware-Architecture class, corresponds to the complete hardware architecture.

the hardware-architecture class

The Hardware interface extends the PrimaryStore interface; the remaining three classes are represented as private instances and cannot be directly accessed from outside the class implementing the Hardware interface. The private members of the Hardware class are accessed indirectly through Primary Store, as described in various sections of the hardware architecture description.

The simulator creates a single of instance of the class implementing the Hardware interface. The system class has three public members: its constructor, an initialize-and-execute routine, and a pointer to an object of type class memory. The first two public members should not be accessed by operating system code; only the pointer to memory is properly a public member.

The PrimarayStore interface defines the fetch() and store() methods to read and write Primary Store. There are a few other public members available to help simplify code; see PrimaryStore.java in the class directory for details.

The Hardware interface Hardware.java defines a number of named constants that act as parameters for the hardware architecture; such parameters include Primary Store size, the way Primary Store’s partitioned into System, User, and Device Space, and so on. See Hardware.java in the class directory for details. The actual value of the named constants may change at any time; it is important that your code use the named constants and not the actual values.

The Simulator-Operating System Interface

As explained above, the interrupt handler is the interface between the simulator and the operating system code. When an interrupt occurs, the simulator stops executing the user process and calls the function

void interrupt_handler(interrupt_types);

passing in the identifying code for the interrupt. Your code takes over, and what happens after that is entirely up to you. When your interrupt handler returns, either by a return statement or by falling off the end of the interrupt handler, the simulator resumes executing the user process.

the user-process os interaction

This see-sawing between the user process and the operating system continues until there are no more user processes to execute, at which point the operating system halts the system.

The interrupts that occur may or may not be a result of the executing user process. If the user process makes a system call, then it will generate a system-call interrupt. If, however, the operating system starts a disk read to bring in the next user program, then the resulting disk-io interrupt has nothing to do with the executing user process.

When the simulator starts, it calls OperatingSystem.interrupt() with the identifying code for a reboot interrupt.

Writing the Code

Because the system is represented as a Java class, you need to write your operating system in Java. You may use whatever design and implementation techniques you’re comfortable with. You are not required to implement operating system data structures using Primary Store; for example, the process table can be a Java data structure. You are also not required to implement any of the operating system in Primary Store, although you may find it necessary to implement tiny helping pieces there.

The simulator and my implementation of the operating system were developed using Java version 6. Relying on backward compatibility, it should be possible to implement the assignments with an earlier Java version, but it’s probably best to upgrade to (or install) the most recent JDK.

To compile file.java, use the command
javac -cp /export/home/class/cs-os/pai/pai-yymmdd.jar:. other-options file.java
where i is the assignment number (1, 2, 3, or 4) and yymmdd is the date for the most recent jar file. For example

$ javac -cp /export/home/class/cs-os/pa1/pa1-120207.jar:. -Xlint scheduler.java

$

-Xlint is a javac option that checks for legal but questionable code.

Debug Printing

As a convenience, the simulator defines the main.debugPrinter.log() method for printing debugging messages to std-err. The advantage to using main.debugPrinter.log() over printing to std-err is that you can use the -d option on the simulator command line to control which main.debugPrinter.log() calls generate output.

The main.debugPrinter.log() prototype is
void log(String flag, String msg)
The flag argument determines whether a particular main.debugPrinter.log() call produces output. A main.debugPrinter.log() call produces output only if the flag argument appears as part of a -d option on the simulator command line. For example, the main.debugPrinter.log() call

main.debugPrinter.log("interrupts",
  String.format("tick %4d:  %s interrupt raised.%n",
    clock, Hardware.Interrupt.reboot));

produces output if the flag "interrupts" (without the double quotes) appeared as part of a -d option on the simulator command line; if "interrupts" didn’t appear as part of a -d option, then the example main.debugPrinter.log() method call produces no output.

For more complicated output, the debug printer also supports the isFlagged() method to test if a flag was given in the -d simulator option. The method signature is

boolean isFlagged(String flag)

For example

if (main.debugPrinter.isFlagged("syscall")) {
  // Really complicated output about system calls or whatever.
  }

isFlagged(flag) returns true if and only if flag appeared as part of the flag-list argument to the -d simulator command-line option.

Running the Simulator

The general simulator command line is

java -cp /export/home/class/cs-os/pai/pai-yymmdd.jar:. \
    main [options] osClass batchDisk [terminalInput]

where

The backslash (\) is shell notation for breaking up a long line into several smaller lines. For example

$ java -cp /export/home/class/cs-os/pa1/pa1-120218.jar:. \
    main os /export/home/class/cs-os/pa1/pa1-empty.dsk

The system is halted.
Total execution time:  10 ticks, idle time: 9 ticks (90%).

$

The .dsk extension may be omitted:

$ java -cp /export/home/class/cs-os/pa1/pa1-120218.jar:. \
    main os /export/home/class/cs-os/pa1/pa1-empty

The system is halted.
Total execution time:  10 ticks, idle time: 9 ticks (90%).

$

If the programs on the batch disk do terminal I-O, the simulator command-line should also contain a terminal-input file. For example

$ java -cp /export/home/class/cs-os/pa2/pa2-120311.jar:. \
    main os.class /export/home/class/cs-os/pa2/pa2-ttycopy.dsk \
    /export/home/class/cs-os/pa2/pa2-ttycopy.tty

The system is halted.
Total execution time:  2653 ticks, idle time: 785 ticks (29%).

$ 

The .tty extension may be omitted. If the terminal-input file has the same name as the batch disk, the terminal-input filename may be omitted, and the simulator will automatically open it:

$ java -cp /export/home/class/cs-os/pa2/pa2-120311.jar:. \
    main os.class /export/home/class/cs-os/pa2/pa2-ttycopy.dsk

The system is halted.
Total execution time:  2653 ticks, idle time: 785 ticks (29%).

$ 

The simulator does not change the device simulation files; the same files may be used repeatedly, independent of the I-O operations performed on the device. At the end of a simulation, the simulator creates the files results.dsk and results.tty. The file results.dsk represents the state of the disk at the end of the simulation; the file results.tty contains all the data sent to the terminal during the simulation. If a device is not written to during a simulation, the associated results file is not created.

The -d Simulator Command-Line Option

The -dflag-list command-line option controls which of the main.debugPrinter.log() calls writes output to std-err. The argument flag-list is a comma separated list of debugging-print flags; spaces should not appear in the list.

If a main.debugPrinter.log() call includes one of the listed flags in its flags argument, then it writes to std-err, otherwise, it produces no output. For example, given the main.debugPrinter.log() call

main.debugPrinter.log("time", String.format("The time is %d.%n", read_clock()));

The command-line option -d time causes the call to produce output; the call produces no output if the command-line option was -d interrupts,systemcalls.

The simulator defines some flags you may find useful:

This page last modified on 2012 March 12.

Creative
    Commons License