Download Jeeves System Manual

Document related concepts

Register renaming wikipedia , lookup

Unisys 2200 Series system architecture wikipedia , lookup

Transcript
Jeeves
24 June 2017
System Manual
1
Introduction
Jeeves can be thought of as a typical, interrupt-driven server system, although it is
completely simulated. Jeeves seems to have the usual complement of hardware, although
some of it runs slower than is typical today and some is smaller in capacity than is typical
today.
Nevertheless, Jeeves functions like a modern server system in most respects.
Generally, the slow speed and small sizes are there only to keep the simulation reasonable.
From this point on, Jeeves will be described as if it were a real machine (with a few minor
exceptions to describe aids that the simulator provides which would not be present on a real
machine).
The basic hardware components for Jeeves are as follows:
Clock
The internal clock speed is only 100 KHz. So, there is a clock tick every 10
microseconds. Most CPU instructions take fewer than 3 clock ticks. The clock
value is kept in the clock register and may be accessed whenever needed.
When the simulation begins, the clock register is set to time 1; it is then
advanced for each tick. The very slow clock and execution speed allow the
scripting to be done without dealing in 9-digit numbers.
CPU
There is a single CPU that can run in either supervisor mode or user mode. In
supervisor mode, activity at the CPU can proceed without possibility of being
interrupted from the system devices - all interrupts and traps are masked when
this mode is in effect.
The operating system and the system programs
(daemons) execute in supervisor mode. In user mode, any event requiring
attention at any of the devices or processes halts the CPU activity with an
interrupt or trap that must be addressed by the operating system.
User
programs execute in this mode. The CPU also has a collection of registers
Jeeves
24 June 2017
System Manual
2
which the operating system needs to access and control the hardware actions see later discussion.
Timer
There is a timer (alarm clock) which may be set on Jeeves. It is used to
control execution time of user programs. To use it, the operating system sets
the timer register to some future time (measured in ticks). When that time is
reached, a Time_Out interrupt is generated.
Memory
There are considerably more than 128 K bytes of memory; however, only 128 K
bytes are available for user programs and buffers - this is the memory that the
operating system must manage.
The operating system (OS from now on)
kernel and the daemons reside in additional, separate memory. The 128 K
memory is byte addressable but is organized into sixty-four 2048-byte page
frames. Jeeves is a virtual memory machine - the 128 K of physical memory
has addresses from 0 to 131071, with page frames beginning at addresses 0,
2048, 4096, 6144, etc. The memory is referred to in some places by physical
page frame number, so page frames beginning at 0, 2048, 4096, 6144 would
be in frames numbered 0, 1, 2, and 3.
Disk
Jeeves has a single 3-platter hard disk; so there are 6 available surfaces
(numbered 0-5). Each surface has 128 tracks numbered (0-127); and each
track has 32 sectors (numbered 0-31). Each sector holds 512 bytes. Thus,
the total capacity of the disk is 12582912 bytes (12 MB). The disk is normally
accessed for reading or writing 4 sectors (a cluster) at a time; however, any
contiguous group of sequentially numbered sectors in a single track can be
accessed in one disk action. The use of the storage on the disk is tightly
controlled by the structure of the file system - see later discussion. The disk
spins at 7200 rpm giving it an access time of 3 ms to 14 ms (average access
Jeeves
24 June 2017
System Manual
3
time is 8.25 milliseconds - 825 clock ticks).
Console
This really consists of three devices which are physically attached to the other
components of Jeeves.
Keyboard
the standard one found on PCs - each keystroke causes an
interrupt. Keystroke frequency depends on typing speed.
Screen
mostly character-oriented, although it can accept one or more
lines of output for display in a single operation. The display rate
for the screen is approximately 10K bytes per second; up to
2048 bytes can be accepted for display at once. The screen is
treated as an output device involving interrupts; it is not memory
mapped.
Mouse
with a roller ball to control a pointer and a single button to
initiate action; not used for the project.
Communications Interface
This is the connection to the network. A TCP/IP-like protocol is used with the
packets sent and received over the network. Clients at other IP addresses can
use the services that Jeeves provides by establishing connections with the
server (Jeeves' IP address is 144.201.193.179). The services available from
Jeeves are Telnet and FTP. (For Telnet clients, Jeeves also acts as a printer
server; it is not a general printer server.)
The interface has a one Mb
connection to the outside world, allowing packets to be sent or received at the
rate of about one byte each 10 microseconds (approximately one byte each
clock tick).
Jeeves is one server on a LAN with a bus topology.
Consequently, Jeeves receives some packets that are intended for other
servers; as in real life, these packets are to be ignored. Only packets destined
for Jeeves should be processed by Jeeves.
Jeeves
24 June 2017
System Manual
4
Printer Jeeves uses a typical buffered printer but with a small buffer. It can buffer up to 8K
bytes; so when printing a file, often only part of the file can be sent to the
printer before it must print. Transmission of data from memory to the buffer
occurs at approximately one byte per microsecond (10 bytes per clock tick).
Once it is signaled to print, the printer prints the contents of its buffer at a rate
of 16 K bytes per second (so a full buffer takes 50000 ticks to print). Ejecting
a page on the printer takes up to 0.05 seconds (5000 clock ticks).
Interrupts
Jeeves is driven by the occurrence of interrupts and traps. An interrupt is regarded as
a signal from some system element (hardware) away from the CPU which indicates the need
for the operating system's attention.
A trap is regarded as a signal from the executing
program which indicates the need for the operating system's attention. When an interrupt or
trap occurs, the hardware does the following:
1.
Changes to supervisor mode (if it is not there already).
2.
Puts an interrupt code in the icode register. The code indicates what type of event
has occurred or what type of attention is needed. The interrupt code is a number
between 1 and 13.
3.
If the interrupt is from a device (keyboard, screen, printer, disk, comm interface,
mouse), the hardware puts the device number into the device register. If the interrupt
is from booting up or powering down or if it is a trap, nothing is put in the device
register.
Jeeves
24 June 2017
System Manual
4.
5
Calls the function OpSys() which is expected to be the entry point to the operating
system for all interrupt and trap handling.
The following tables lists the interrupt and trap codes that Jeeves uses. Associated
with each code is a name (used to refer to the specific interrupt/trap in subsequent
descriptions) and a cause that gives a basic explanation of what caused the exception.
Code
1
Common Name
Type
Cause
Boot_Done
Interrupt
Machine has been powered up and the
operating system has been loaded into
memory by the program in PROM.
2
Power_Down
Interrupt
Person at console has pushed the button to
turn power off.
3
Device_In
Interrupt
Input has been received from some source:
key from keyboard, packet from interface,
cluster from disk, mouse movement.
4
Device_Out
Interrupt
Output has been delivered to some
destination: text to the screen, data to the
printer, cluster to the disk, packet to the
interface.
5
Device_Enable
Interrupt
The printer has come on line; it was
previously disabled for some reason. The
printer always starts online.
6
Device_Disable
Interrupt
The printer has gone off line; it will reenable at some point.
7
Control_Done Interrupt
A device has completed a control action: seek on
a disk or eject on a printer
8
Block_Self
Trap
A system program has completed its task
Jeeves
24 June 2017
System Manual
6
and needs to be moved to a blocked state.
9
Time_Out
Interrupt
The time set in the timer has been reached
or exceeded.
10
User_Pgm_Input
Trap
A user program has requested to read
some data from a file.
11
User_Pgm_Output
Trap
A user program has requested to write
some data to a file.
12
User_Terminate
Trap
A user program has reached a successful
conclusion.
13
User_Abort
Trap
A user program has attempted some action
that is not allowed and must be terminated.
Each device on the system is referred to by its device number. When interrupt codes
3, 4, 5, 6 or 7 occur, it is vital to distinguish which device the interrupt code should be
associated with. Following is a list of the device numbers used on Jeeves:
Device
Device Number
Comm Interface
20
Disk
19
Keyboard
Mouse
9
51
Printer
Screen
23
16
How It All Gets Started
Jeeves
24 June 2017
System Manual
7
The simulator works with two (or three) data files: one contains the information for
Jeeves' disk; a second contains a script of events to exercise your operating system. The
optional one is used for tracing purposes, see later description. To start the simulator, your
program must call BootStrap() in main; BootStrap then does the following:
1.
It sets up a simulation with the specified disk and script files.
2.
It acts as if memory is being checked and your operating system and its system
processes are being loaded from the disk.
The disk already holds the bootstrap
program, the operating system, a starter file system and some user authentication
information. The simulator notifies you if any problems occur during this the setup.
(This step is completely fake - your OS is not really on the disk, neither are the
system processes.
3.
It then issues a Boot_Done interrupt to give your operating system control, by calling
OpSys with the interrupt code set to 1.
At that point, your operating system should take over. You may assume that all of the
standard devices (console, comm interface, disk, and printer) are available at that time. Your
operating system should set up its data base of information about the devices, the users, the
processes (it should create six system processes initially) and the threads. The OS should
then begin thread scheduling.
When you run the simulator, it prompts you for two pieces of information. It asks for a
script file name and a disk name. The script file contains a script of mostly input interrupts
(keystrokes and Comm Input messages) and a few other events (Boot_Done, Device_Enable,
and Device_Disable interrupts). The disk is actually kept in a file also. The disk file contains
Jeeves
24 June 2017
System Manual
8
the information held on the simulated disk. Below is a display of exactly what appears when
the simulator executed for one script; naturally, the number of bytes varies from script to
script. The elements in bold are the entries specified for a simulation run (by you).
Enter script file name: comm1.scr
133 byte script ready.
Memory OK
Peripherals present: Console, Comm Interface, Printer
Console elements: Keyboard, Screen, Mouse
Enter disk name: thedisk
Disk is ready.
All other hardware is ready.
Operating system loaded -- Transferring control to it.
If your OS does not cause any errors, this may be all the output to the screen that you see
during a simulation. Other possible outputs to the screen and other files are described later.
Registers
Jeeves has a collection of registers that are used by the operating system to direct the
devices and by the devices to communicate information to the operating system. Nearly all of
these registers can hold 32-bit integer values. These registers are described in three groups
based on their function. Below is a list of the general registers and what they are used for.
Each of these registers is referred to in your OS as
R.registername
Jeeves
24 June 2017
System Manual
9
General Registers
Name
Purpose
clock
Keeps the system time (measured in units of 10 microseconds). The OS may
get value of clock anytime, but it cannot change it.
timer
Holds a system time at which to raise an alarm (interrupt code 9). The OS
may set this to any system time. If timer <= clock, a Time_Out interrupt is
raised unless timer is set to -1 (its "off" value).
icode
Interrupt code number. The OS can get this value; but it cannot set it.
device
Interrupt/command device number. The OS can get the value here when an
interrupt occurs to determine which device needs attention. The OS must set
the value of this register in conjunction with checking the status of a device,
with resetting a device or with issuing a command to a device.
state
Contains a status code for a device which was just interrogated with the
GetStatus instruction. The state must indicate a device is "ready" before an
I/O command can be issued to the device. The possible state codes are 0 to
indicate "ready", 1 to indicate "busy", 3 to indicate "locked", 4 to indicate
"disabled", 7 to indicate "unstable", and 9 to indicate "unknown".
pc
Holds the relative (virtual) memory address of the next instruction to execute for
the executing process. This is the program counter.
genpur[8]
This is the collection of general purpose registers that are used for running any
program.
oserror This would not be a register on any real machine. When the simulator detects an
error that your OS has made, it displays an error message and puts an error
code in this register. In this way, the OS can determine if an action that it
attempted failed; a value of zero in this register indicates "no error."
In addition to the general registers (useful for many actions), there are two groups of special
Jeeves
24 June 2017
System Manual
10
use registers. The first of these is for control of input and output. The registers in this group
are referred to as R.io.registername in your OS; each is described below.
I/O Registers
Name Purpose
address
Physical memory address of the beginning of an area to be used in a data
transfer. The OS must set this register prior to issuing a command that is
expected to result in data being transferred from memory (and to memory in the
case of the disk). For I/O involving disks and printers, the address must be a
multiple of 2048 - disk I/O and printer output must begin on a page frame
boundary.
datasize
Number of bytes to be transferred to or from the memory area whose beginning
is specified in address.
The OS must set this register prior to issuing a
command that is expected to result in data being transferred from memory
(and to memory in the case of the disk).
packetin
Holds the physical memory address of where the next packet to arrive over the
communications interface is to be placed.
mousein
Holds the physical memory address of where the information about the next
mouse action is to be placed.
keyin
Holds the physical memory address of where the next character from the
keyboard is to be placed.
surface
The surface number of where to access the disk.
track
The track number within the surface to access.
sector
The sector number within the track at which to begin the access. Most disk
accesses are expected to access 4 consecutive sectors (a cluster); the exact
number of sectors is determined by the datasize register. The datasize must
be a multiple of 512 (the number of bytes in a sector). The sector value is
Jeeves
24 June 2017
System Manual
11
usually a multiple of 4.
action
The action to take (a char): R to read from the disk to memory, W to write
from memory to the disk, S to seek only on the disk, B to write from memory
to the printer buffer, P to print the contents of the printer buffer, or E to eject a
page on the printer. This character must be in uppercase.
bufferaddr
The printer buffer address to which a transfer from memory is to be made,
beginning at R.io.address.
The second group of special purpose registers is for process and thread control actions. For
all but two of these registers, it is necessary for the OS to set specific values into them before
trying to execute a process. The two exceptions are registers that are set by user programs
when requesting the OS to perform some I/O. The process control registers are referenced
in the OS as R.process.registername each is described below.
Process Registers
userid
The user identification number of the user who owns this process. This number
is found in the password file and is permanently associated with a user. This is
useful when executing user programs.
processid
This number is assigned by the OS. Each process gets a processid when it is
created. The system processes have special processids that must be assigned:
the DiskScheduler must have processid == 1, the ProtocolHandler must have
processid == 2, the Login handler must have processid == 3, the Shell must
have processid == 4; the Unspooler must have processid == 5; and the
Transmitter must have processid == 6.
User processes are assigned
processids on an as needed basis - these processids must be > 10 (so, the
first user process should have processid == 11).
thread This number is used to allow a user program or system process to be used in a
reentrant manner; it is a number that is distinct for each executable element
Jeeves
24 June 2017
System Manual
12
(each communication session or console login). If user xyz was logged in
three times from separate client machines and was executing the same process
(e.g. Shell) on each of them, the thread would distinguish the three instances.
If the user logs in, does something, logs out, and then logs in again from the
same IP address, these are separate threads. Thread numbers begin at 101
and are allocated sequentially as each session's SYN is received. Generally, a
thread number should be maintained throughout the life of a session, regardless
of which process (system or user) is executing.
ipaddr The IP address of the client responsible for this thread.
pgmioaddr
The relative memory address at which a user program wants input read into or
output written from. In each case, a data record is being transferred. System
processes do not use this register.
pgmiosize
The number of bytes to be transferred in a user program I/O action. For input,
pgmiosize is the maximum number of bytes allowed for reading - each read
generally reads one record of a file; for output, pgmiosize is the actual number
of bytes to write. System processes do not use this register.
pagemap[16] This provides a hardware page map for translating virtual memory addresses to
physical memory addresses. Each element of this array is a page map
entry; each entry is four bytes long.
A page map entry has three
named components:
resident:
Residency flag - 1 resident in memory, 0 not resident; referred to
a R.process.pagemap[x].resident for the xth pagemap entry
valid:
Validity flag - 1 refers to part of the program, 0 does not refer to
the program (or its data)
pageframe:
Page Frame Number - used for address translation of virtual to
physical addresses
To execute a user program, the OS must assign it to available page frames in
Jeeves
24 June 2017
System Manual
13
memory and then copy the program into them. The assigned page frames
determine what values to place in the pagemap. For small user programs,
many of the pagemap entries will have valid == 0
and
resident == 0
System processes use only pagemap[0]; the pageframe value used for these
are always the same: DiskScheduler 91, ProtocolHandler 92, Login 93, Shell
94, Unspooler 95, and Transmitter 96, respectively. Naturally, the valid and
resident values for the system processes are 1 for pagemap[0].
Privileged Instructions
There are 8 privileged instructions on Jeeves.
Today, every system has some
instructions built into it that only the operating system (kernel or daemons) may use; i.e.,
instructions that can be executed only in supervisor mode. For Jeeves, your OS uses these
instructions in a form that looks like a call to a function which has no arguments and returns
no values.
Three of the privileged instructions are used for setting up, initiating and
acknowledging I/O actions; the other five are for relinquishing control of the CPU in various
ways. Each is described below.
GetStatus()
Requires that R.device be set to a valid device number. Returns in R.state the
status of the specified device - see R.state for an explanation of the state
values (codes).
StartAct()
Requires that R.device be set to a valid device number, that R.io.address and
R.io.datasize be set to the starting location and number of bytes to be
transferred, respectively. In addition for printers and disks, R.io.action must
specify the operation; for the disk, the disk location registers must be set; and
for the printer the R.io.bufferaddr register sometimes must be set. StartAct
Jeeves
24 June 2017
System Manual
14
causes the I/O operation to get started. StartAct does not change any register.
Clear()
Requires that R.device be set to a valid device number. This instruction resets
an input device that spontaneously interrupts (i.e., not the disk or the printer)
so that subsequent input will cause an interrupt. For example, after a keystroke
or a packet arrival, the OS must issue a Clear so that subsequent keystrokes or
packets can arrive. Clear changes R.state to zero.
RunUser()
Requires that the R.process registers be set to the specifications of the user
thread to execute (user id, process id, thread number, IP address, and
pagemap), that R.pc be set to the program counter of where the thread last
stopped (or to zero if the thread is just starting) and that R.genpur[] registers
be set to the values in the general purpose registers when the thread last
stopped (or to zero if the thread is just starting). When the OS uses this
instruction, Jeeves enters user mode and the specified thread resumes/starts
execution.
RunSys()
Requires that R.process.userid, R.process.processid, R.process.thread, and
R.process.ipaddr be set to the specifications of a system process. The six
system processes that you must have are described later. When a system
process runs, Jeeves is in supervisor mode.
Block()
No setup is required. Only a system process can issue this instruction, without
causing a possible infinite loop in the OS. When a system process has finishes
executing for a thread, it must use Block to notify the OS that it wants to stop
executing and have the thread placed in a blocked state or associated with a
different process. This instruction causes a Block_Self trap to occur to give
control to the OS kernel. The OS should then perform the appropriate action
Jeeves
24 June 2017
System Manual
15
on the system process and resume kernel actions.
Jeeves remains in
supervisor mode throughout.
Wait()
No setup is required.
Makes the CPU idle and changes to user mode.
Nothing uses the CPU until an interrupt occurs; devices which have been given
commands continue to work on their assigned actions.
Halt()
No setup is required. Terminates the simulation and causes the analysis report
to be displayed.
How Do You Use All This?
At this point, the long list of hardware components, types of interrupts, registers and
privileged instructions might seem to be lacking in one thing - an explanation of what to do
with it all. That, of course, is what an operating system does; it controls the hardware on
behalf of the users of the system - in this case the clients of this server. Following is a
general description of how your operating system would use the hardware. It is general
because you are allowed to design your operating system in any manner you want as long as
it meets certain requirements - see a later section.
Consider how a server system is supposed to behave. When it is booted (when a
Boot_Done interrupt occurs), the OS must take control and be ready to serve the clients who
are out there somewhere at some IP addresses and want to have the server do things for
them. The server system you are making can provide two types of service: Telnet - allowing
users to log in and give commands (just as if they were at the console) and FTP - allowing
users to transfer files to and from the server. The clients may be on the same LAN as
Jeeves or anywhere else in the Internet world.
Jeeves
24 June 2017
System Manual
16
So, at the Boot_Done interrupt, the OS must prepare for the onslaught of client
messages from the Comm Interface, as well as possible activity from the console. To manage
authentication and the handling of clients and their files, the OS must set up a collection of
information about the Interface, the console, the printer, the disk, the clients, their processes
and threads, various system processes that will be needed, the messages that are being used,
and the memory. This collection of information is often called the OS database. This is not a
database in the COSC 341 sense; there are no relations or attributes or queries, although
there are some similarities in terms of conflict with a normal database. The OS database is
the collection of data structures or objects that the OS uses to control what is going on.
At the Boot_Done interrupt, the OS should begin to build its database.
Some
information is available from the disk; it already has a file structure on it. Your OS should
start reading in critical information from the disk, such as the disk bit map, the root directory,
the password file, perhaps the users directory - these are described in a later section.
The OS should also make the console ready by prompting for a login. Normally, only
the root user might be allowed to login to the console; but for Jeeves, any user is allowed to
login at the console. This user would want to be able to do any of the commands that a
Telnet client could do; if the user is root, even more capability than normal clients is expected.
Getting information from the disk involves reading it.
ALL OS initiated device
operations occur in the following sequence.
1.
The OS must verify that the device to be involved is ready. Your OS would do this by
using the GetStatus privileged instruction; this instruction places the status of the
specified device in the R.state register. If the returned state is 0 (Ready), the OS can
proceed to the next step. If the state is 7 (Unstable), an electronic anomaly has
Jeeves
24 June 2017
System Manual
17
occurred - these are fleeting; normally by simply getting the status again, a regular
status is returned. If the state is anything else (1 Busy, 3 Locked, 4 Disabled, 9
Unknown), the OS should not have done the GetStatus. The OS should be keeping
track of the device state; the act of doing a GetStatus should be a formality; the OS
should be expecting Ready every time it does GetStatus. If the OS doesn't expect a
Ready state, it isn't paying attention. . . . When a device is ready,
2.
Set the appropriate registers - these always include the R.io.address and R.io.datasize
registers; for disks, these include the location and action registers; and for printers,
they include the action and buffer address registers.
3.
Then, the OS must use the StartAct privileged instruction. There is nothing more the
OS can do until the device completes the action and causes an interrupt.
4.
The OS must either run a user process (RunUser), a system process (RunSys) or do
nothing (Wait)until the device is done.
A disk takes an average of 825 ticks to
complete; for the screen, the printer or output to the Interface, the time required for an
action is also variable, based on the amount of data being transferred.
When a device completes a directed action, either a Device_In, a Device_Out or a
Control_Done interrupt occurs; i.e., one of these codes is in R.icode. When any of these
occurs, the R.device register holds the number of the device causing the interrupt. The OS
must use the R.device and R.icode values (and other information maintained in the database)
to know whose action has just completed and how to respond.
There are also interrupts that occur with no command coming from the OS. As
examples, the user at the console can press a key or move or click the mouse; a client can
initiate a connection or a command that appears to the server in the form of a message
Jeeves
24 June 2017
System Manual
18
packet. Because the OS has no idea when these interrupts might occur; it must be ready for
them any time the system is in user mode. When a keystroke, or a message or a mouse
action occur, the OS must have provided an appropriate size buffer area in memory to hold
the data arriving from the device.
The OS prepares to do this by setting the R.keyin,
R.mousein and R.packetin registers with the addresses of the buffer areas as part of its
preparations at the Boot_Done interrupt. When one of these interrupts occurs, the hardware
puts the device number into R.device, a 3 into R.icode and the data into memory. The OS
must make provisions for another such interrupt by moving the data from the buffer or making
one of the registers point somewhere else. The OS must also clear the device so the device
can issue another interrupt - this is done with the Clear privileged instruction. When any
uninitiated interrupt occurs on a device, the device's state becomes "Locked" (R.state is 3).
The Clear instruction restores a ready state to the device, thereby allowing more input (and in
the case of the Comm Interface, more output).
The Device_Enable and Device_Disable interrupts are limited to occurring at the printer
and like keystrokes, mouse actions and packet arrivals, can occur at any time. The printer is
initially enabled when the system starts. If it sends a Device_Disable interrupt, it is saying
that it cannot accept commands, at least not until it signals again with a Device_Enable. If
the OS issues a command to a printer and that printer sends a Device_Disable instead of a
Device_Out or Control_Done interrupt (which would indicate completion), the OS must reissue
the command after the printer sends a Device_Enable. If the printer is not busy when it
sends a Device_Disable, the OS must simply delay issuing any commands to it until it sends
a Device_Enable. You may assume that the printer will always send a Device_Enable; you
just cannot be sure when that will happen.
When a packet arrives at the Comm Interface, the OS must perform several tasks in
addition to the "device driver" actions of clearing the interface and manipulating buffers.
These actions include:
1) make sure the message is valid and intended for Jeeves, 2)
Jeeves
24 June 2017
System Manual
19
identify the source IP and associate that with a thread on the server (or create a new thread),
3) determine the nature of the message (part of authentication or a command), 4) perform
authentication or parse the command, and 5) if it is a valid command, begin to perform the
requested action. All of these actions are handled by system processes - described in a
later section.
Sometimes a client issues a run command to execute a program on the server. The
run command specifies a file containing the executable program, a file containing the input,
and a file to contain the output. To accomplish reading of the input, writing of the output and
program termination, several trap actions come into play. To execute a user program, the OS
must load the program file into memory, set up the R.process registers, including the
R.process.ipaddr and R.process.pagemap[] registers, and do a RunUser privileged instruction.
At that point, the system goes into user mode and the user program begins to execute.
Soon the program starts generating traps that the OS must deal with.
There are four types of traps generated by user programs: User_Pgm_Input requests
the logical reading of a record (line) from its input file - the OS response is to do whatever it
takes to get the record to where the program wants it. User_Pgm_Output requests that an
output record (line) which the program has produced be logically appended to the output file the OS response is to do whatever it takes to get the record from where the program is
holding it to the output file. User_Terminate and User_Abort announce that the program has
come to an end (successfully or not) - the OS response is the same in either case - finish
output to and close the output file and release the resources (memory and files) the program
is using. More details later.
The OS may choose to use the R.timer register to provide additional control of the user
program' actions (highly recommended). Prior to starting/resuming a user program with a
RunUser instruction, the OS can set the R.timer register to some future clock time. When that
Jeeves
24 June 2017
System Manual
20
time is reached, a Time_Out interrupt is generated. This gives the OS an opportunity to stop
the executing user program and allow another process to execute. Note: When a Time_Out
interrupt occurs, R.timer must be set to another future time or be turned off (set to -1). If
neither of these is done, Time_Out interrupts are generated continuously.
How is the OS Structured?
You have considerable flexibility in deciding exactly how components are arranged;
however, the overall structure of the OS must fit the following model.
Kernel
The OS kernel (central part) must contain the code to handle Database Setup, an
Interrupt Direction Mechanism, Device Drivers, and the CPU scheduler. These elements must
be direct or indirect parts of OpSys(). The first three of these tasks have been addressed in
the previous section; CPU scheduling is covered below. To handle the other key tasks, the
OS can rely on six system service processes (sometimes called daemons). Auxiliary tasks
may be taken care of in any place that you (the designer) wish.
You may not have recognized the Interrupt Direction Mechanism and the Device Drivers
in the previous discussion. When the hardware calls OpSys(), it already has various registers
set to indicate the nature of the interrupt or trap. The kernel must react to the exception by
performing an appropriate Interrupt Service Routine (ISR). The Direction Mechanism is the
decision making necessary to get to the ISR. Device Drivers handle the details associated
with a device - for a Keystroke or a Comm Input, that includes storing the data and perhaps
clearing the device status; for output to anything, it includes setting the registers and initiating
the act. There is more discussion about output later.
Jeeves
24 June 2017
System Manual
21
Your OS is expected to schedule threads to use the CPU. A thread is usually defined
as a unique instance of an execution of a program. A process is a program in execution.
So, if two clients both execute the same program, there are always two threads involved
because there are two instances of execution; however, there may be one or two processes,
depending on whether the program is loaded into memory once or twice. On Jeeves, each
client is expected to have his/her thread of execution identified by a number (starting at 101).
Then, regardless of which program the client is executing, that client's thread has the same
assigned number. Two system processes (Login and Shell) are expected to allow multiple
simultaneous threads, more than one thread executing the same copy of the process. All
other system processes and all user program processes are limited to one thread at a time.
To schedule the CPU, the OS must establish the context of the thread to be executed.
The context consists of the settings of the R.pc, R.genpur, and all R.process registers.
These values must be restored to whatever they were when the thread last executed so that
the thread can resume execution exactly where it left off. Setting of the context is required
whether the CPU is to be executing a system or a user process. Your OS must allow all
ready threads to have an opportunity to execute; it must be fair in selecting the next thread to
execute; it must not allow threads to wait indefinitely to execute. Consequently, the OS must
have one or more mechanisms for changing the executing thread.
System processes are always resident in memory; but user processes must be loaded
into memory and require more elaborate support. To execute a user process thread, the OS
must reserve enough page frames in memory to hold the entire program, plus one additional
page frame to hold the program's data. It must read the program into the page frames and
set up the page map. It must reserve one page frame as an input-file buffer and another
page frame as an output-file buffer. And the OS must support the unblocking of input records
and the blocking of output records to allow the user process threads to function normally.
Jeeves
24 June 2017
System Manual
22
Daemons (System Processes)
The task of directing incoming packets to the appropriate receiver is performed by the
ProtocolHandler daemon. The task of directing outgoing packets to the appropriate client is
performed by the Transmitter daemon. The task of authenticating clients is performed by the
Login daemon. The task of responding to client commands (entered via Telnet or FTP) is
performed by the Shell daemon. The task of scheduling the use of the disk is performed by
the DiskScheduler daemon. The task of getting files printed on the printer is performed by the
Unspooler daemon. By modularizing the OS and separating out several of the tasks, the
design and construction or your OS should go more smoothly.
Some tasks (conflict
resolution, memory management, file management, etc.) may be distributed throughout the OS
or may be centralized, as you choose.
Although you are required to write them, the six system processes are a part of your
OS that you are NOT allowed to use directly. They are processes whose threads must be
scheduled to use the CPU; each system process thread must be executed when necessary by
using the RunSys instruction (with R.process.processid indicating which process to run). In
addition, each of the processes must appear as a single void function with no arguments in
your OS (although they are permitted to call any other functions that you have in your OS).
The processes functions must be named DiskScheduler(), ProcotolHandler(), Login(), Shell(),
Unspooler(), and Transmitter(). The functions have a form requirement: At the end of each
one, the Block instruction must be used to tell the kernel that the thread is done for the
moment.
ProtocolHandler
Although Jeeves does not use the complete 7-layer OSI network model for
communications, there are elements of four layers that your OS must deal with. The data link
Jeeves
24 June 2017
System Manual
23
layer, which deals directly with the hardware, is handled very simply with interface input and
output device drivers. Here your OS must respond to the interrupt caused by receiving a
message and pass the packet to the network layer for validation and authorization. The
network layer examines the IP header to check the IP addresses, to determine that the
message is in tact, to find the size of the data, to assemble messages that are sent in pieces,
etc. After passing these tests, the whole message is taken by the transport layer which uses
the TCP header to determine the application that is to act on the contained data. Here the
sequence number is also noted so that communications can be kept organized.
The
application layer (represented by the Login and Shell processes) acts on the messages once
it receives them.
The ProtocolHandler and the input device driver must handle all the
preliminary action to get valid messages to Login and Shell.
The real Telnet and FTP use the TCP/IP protocol suites; Jeeves' Telnet and FTP use
message forms and methods that are similar to the real thing. To understand the actions of
the ProtocolHandler (and the Comm Interface device drivers), you need to know about the
message form and the use of the message elements. Every packet that comes in or goes out
the Comm Interface has three parts: an IP header that contains 20 bytes, a TCP header that
contains 12 bytes, and a data area that may contain from 0 to 512 bytes. Each of these
forms is described below, beginning with the IP Header Form (The Size column shows the
number of bytes used to represent the content information.)
Size
Form
Contents
1
char
Version number - this is always 4 (binary 00000100, ASCII Ctrl-D)
1
char
IP Header length, measured in units of 32 bits - this is always 5
(Jeeves uses IP headers of 20 bytes exclusively)
2
short
Data length, measured in bytes. Because the TCP header follows the
IP header, its bytes are counted as part of the data length. So this
value is never less than 12 and may be as large as 524.
Jeeves
24 June 2017
System Manual
2
short
24
Fragment number. For most messages, this is 0. When data larger
than 512 bytes needs to be sent, the OS must break it into parts and
send two or more message fragments.
Then, this element of the
message is a number indicating which fragment this packet is; for
example, 1500 data bytes would be sent in 3 fragments with fragment
numbers 1, 2, and 3. When incoming data is larger than 512 bytes (as
in a file transfer), the client computer sends fragmented messages to
Jeeves in this same way.
1
char
Fragment total. When messages are fragmented, this field holds the
total number of fragments for the message. For the 1500 data bytes
above, this field holds 3 on all three fragment packets.
1
char
Transport protocol used - this is always 'T' meaning TCP.
2
char
Time to live; the number of hops the message is allowed to take to
reach the client - this is always 64.
2
u short Standard 16-bit cyclic redundancy check value for the header; it is a 16-bit
unsigned short value. This is calculated by setting it to zero, passing
the entire header to the CRC function (provided to you) and storing the
returned result in this element. This value is used for error detection in
the header.
4
ip addr Source IP address for the message, stored in standard class B address form
where the subnet mask is always 255.255.255.0.
That is, each
component of the address is one byte in size. For example, the IP
address for Jeeves is 144.201.193.179 where 144 and 201 specify the
domain, 193 is the subnet and 179 is the host.
4
ip addr Destination IP address in the same form as the source.
From the IP header, the OS can determine all of the following from incoming
messages: 1) where to put the next incoming message which may come in at any time -
Jeeves
24 June 2017
System Manual
25
based on the size of this one; 2) whether there was any error in communicating the message
- recalculate CRC and see if it matches the one in the message; 3) whether the message is
intended for Jeeves; 4) what the source IP address is - if it is an IP address on which there
is no active session, a new thread usually needs to be created; 5) what the data length is to see how much to pass on to the next stage of processing. Usually, the device driver for
the interface input handles action 1), while the ProtocolHandler handles 4) and 5), with 2)
and 3) being done by either.
The ProtocolHandler must have access to information about what threads are active so
it can determine whether or not to create a new thread in response to an incoming SYN
message. There are four message types that are used to establish, maintain and sever a
connection between a client and the server. These message types are part of the TCP
header. We need to look at its 12 bytes next.
Size
Form
Contents
2
short
Source port number. There are 65536 port numbers; Telnet and FTP
use standard ports: Telnet always uses 23 and FTP uses 20 and 21.
So, for Jeeves Telnet, this is always 23; for Jeeves FTP, this is always
20 - Jeeves does not use port 21.
2
short
Destination port number - again the standard for Telnet is 23 and for
FTP is 20 or 21; here always 23 for Telnet and 20 for FTP.
4
long
Message sequence number.
When a client initiates a connection it
begins sending messages and associates a sequence number with each
of them so that the client and server can determine whether messages
have gotten out of order. Most messages that are received require an
acknowledgment; the OS should copy the sequence number from the
incoming message into the response message(s) that it sends back so
that the client knows what has been received.
Jeeves
24 June 2017
System Manual
26
1
char
TCP header length measured in bytes - this is always 12
1
char
Message type: 'S' indicates SYN - used to initiate a connection, first
message a client sends, has sequence number 1; 'A' indicates ACK used to acknowledge a previous message (and often to include
response data); 'P' indicates PSH - used to send data to the server (a
command from a Telnet client); and 'F' indicates FIN - used to abruptly
terminate the connection, may be sent by client or server, no
acknowledgment is sent. Note: real TCP messages can have multiple
types, e.g. 'A' and 'P' to send an ACK that includes data - your OS
should simple use 'A' or 'P' message types to do this. An illustration is
given later.
2
char
Application indicator; for Jeeves this is essentially just used to distinguish
what type of service is to be provided and therefore what client
commands are valid. Jeeves uses 'TN' for Telnet, 'FP' for FTP
The ProtocolHandler must distinguish the message types, verify that the messages are
Telnet or FTP messages, and pass on the data to the appropriate process (Login or Shell) for
action (sometimes creating a thread for a new client). The data part of the messages may
contain a username, a password, a command, or part of a file, depending on the situation. All
of this data is in ASCII character form; there is no message for Jeeves that involves binary
data.
Login
This system process handles all elements of authentication. When the ProtocolHandler
receives a SYN from a new client using the Telnet port, it must create a new thread and
associate it with the Login process. Login must then create an acknowledgment message that
prompts the client to login. For Jeeves, this prompt must be "login please: " including a
Jeeves
24 June 2017
System Manual
27
trailing space but without the quotes.
When the ProtocolHandler receives a PSH from a client, it needs to know to which
process to direct the data. The OS database must maintain information that the Protocol
Handler can check to determine this. If the PSH is from a known, authenticated client, the
ProtocolHandler passes the data to a thread of the Shell process. If the PSH is from a newly
created but not yet authenticated client thread, the ProtocolHandler passes the data to a
thread of Login. (Such a message may contain the username.) Login should save the user
name and create and acknowledgment message that prompts for a password.
When the ProtocolHandler receives the PSH containing the password, it must know to
give the information to Login. Login must then verify that the password is correct. This is
normally done by matching the user name and encrypted password with the entries in the
password file.
You are given the use of the encrypt function to encrypt what the client
entered as a password. If the user name and encrypted password match, Login should mark
the client as "authenticated" and should associate the client thread with the Shell system
process for subsequent packet processing. If there is no match, Login must generate a FIN
message with an error statement in the data and send it to the client to terminate the client's
connection.
Shell
When the Shell first gets a thread, it sends an ACK message containing the system
prompt to the client. The system prompt is
"Jeeves> " with a trailing space. Shell's job is
to accept Telnet and FTP commands from client threads, parse them (based on the service
being used) and, if they are valid, start to perform them. If they are not valid, Shell should
construct an ACK with an error message to send to the client. Shell contains the code to
perform most client requests, except for two commands.
The run command leads to
Jeeves
24 June 2017
System Manual
28
executing a user program which was briefly described previously; and the print command
leads to Unspooler action to control the actual printing, described later.
This was a very brief description. The Shell is a key element in directing the tasks that
the clients want to have performed. See the Suggested Handling of show to appreciate its
central role.
DiskScheduler
This system process should be activated whenever there is some disk I/O to do (and
the disk is not already busy). There may be many reasons for such I/O. To set up the
database, the DiskScheduler must be used to read information from the disk. When a client
logs in, if the database does not contain an up-to-date copy of the password file information,
then the DiskScheduler must be used to read the password file. As clients give commands,
the DiskScheduler is needed to handle the associated disk I/O - consider such commands as
"copy a file", "add a user", "print a file", "change file access". As user programs execute,
they need to access the input and output files; the DiskScheduler is used to read and write
data, respectively. And, as files are printed, the Unspooler must request the DiskScheduler to
read in spooled files. This process is called a scheduler because with all these possible
sources of requests and the fact that the disk can do only one operation at a time, some
component must choose which request to satisfy next, as well as keep the disk busy as long
as there are requests.
Transmitter
The Shell and Login processes may be dealing with many client threads at once.
Consequently, they may generate many output messages during the time that one message is
being transmitted.
Some of these messages may contain multiple fragments. Some
Jeeves
24 June 2017
System Manual
29
component must be able to handle requests to send many messages and the fact that the
Comm Interface can really receive or send only one message at a time. The Transmitter must
keep the messages to be sent going out to the clients as rapidly as the Comm Interface will
allow. Remember all clients (except perhaps the one at the console) are gaining access
through the Comm Interface. The more of them that there are and the more actions they
take, the more messages that need to go through the Interface.
Unspooler
The Unspooler deals with the print queue. When a client enters a print command, the
Shell must take care of copying the file to the spooling area of the disk and putting an entry in
the print queue. At that point, the command is considered complete from the client's point of
view. Consequently, the client should be sent a prompt and the client's Shell thread should
be ready to process the next incoming command.
The Unspooler handles the print request, once it is in the print queue. The Unspooler
schedules the print images (spooled copies of files) to be sent to the printer and, along with
the printer driver, issues the commands to the printer to get the printing done. The Unspooler
works with the DiskScheduler to read the spooled files from the disk. After each disk cluster
is read, the Unspooler must initiate a transfer of the cluster to the printer's buffer. This is
done until the buffer is full or all of the data in the file has been transferred. When either of
these happens, the Unspooler or printer driver must tell the printer to print the contents of its
buffer (thus, emptying the buffer). If more of the file is yet to print, the cycle of disk read buffer transfer - print continues. After the last data of the file is printed, the Unspooler or
printer driver must issue an eject command to the printer so that it advances the paper to the
top of the next page.
When the printer completes this action, the printing of the file is
complete. The Unspooler can then focus on any additional print requests that the print queue
may contain.
Jeeves
24 June 2017
System Manual
30
There is one complication with printing. The printer is the only device which may
become temporarily disabled (unable to perform any action). When the printer becomes
disabled, it issues a Device_Disable interrupt. If this occurs between the time that the
printer has been issued a command and the time it completes that command, the
command is lost. You are guaranteed that the printer will become enabled soon after it
disables; but you don't know exactly when this will happen. Consequently, your OS must be
prepared to re-issue the last command it gave the printer, if that command was lost. Of
course, if the printer disables during a time in which it is inactive, there is no command to reissue; any unspooling action which is needed while the printer is disabled must be delayed
(not abandoned) if such an event occurs.
Suggested Handling of show
One of the commands that clients can request via Telnet is to show a file. This
command requests that the contents of a file be sent back to the client, presumably so the
client can view them. It would be like a cat command in Unix or a type command for VMS or
MS-DOS. To illustrate how the system processes interact to get a task done, a suggested
method of implementing show is outlined below. In addition to the system processes, this
implementation also mentions the roles of the kernel and device drivers.
Let's assume that some client has successfully logged in from IP 1.2.3.4. When this
client sends a packet containing the command: show ./simple.one
it causes a Device_In
interrupt at the Comm Interface. Based on the device causing the interrupt, OpSys should call
the Comm Input Driver to handle the incoming packet.
Jeeves
24 June 2017
System Manual
1.
31
The Driver should put the packet in a queue for processing by the ProtocolHandler and
make the ProtocolHandler process/thread ready to execute (if it is not already). Note
that it is enntirely possible that the driver may need to do this for many packets before
the ProtocolHandler executes. The Driver must also clear the interrupt.
2.
The ProtocolHandler may not be the next process to execute - that depends on the
CPU scheduling algorithm and whether or not there are other processes that are ready.
However, if the CPU scheduler is working properly, the ProtocolHandler will be
selected to execute at some point.
3.
When the ProtocolHandler executes, it should process all the packets in its queue by
directing them to the next level of service. The ProtocolHandler must recognize that
the packet from 1.2.3.4 is from a known IP address and must associate it with the
appropriate next step. The OS must maintain information about all threads in the
system so the ProtocolHandler can determine that this command should be directed to
the attention of a thread of the Shell process. The ProtocolHandler should then make
that thread ready to execute.
The last act of the ProtocolHandler (after handling
everything in the queue) is to block itself with the Block instruction.
4.
As with the ProtocolHandler, there is no certainty as to when this thread of the Shell
will execute; however, when it does, it should try to start or continue the task
presented to it by a client. For the client at 1.2.3.4, Shell should realize that this is a
fully authenticated client and that it is presenting a Telnet command. Shell should
parse the command to make sure it is valid. The command is asking to show the
contents of the file sample.one in the client's own directory (the ./ part) on Jeeves. If
there is any problem with the command (e.g., if sample.one did not exist), the Shell
thread should generate an error message (an ACK) and enqueue the message for the
Transmitter to send to the client. But, this is a valid command, so the Shell thread
Jeeves
24 June 2017
System Manual
32
begins to do the command - it must begin to read the file.
5.
The Shell thread assigns memory buffer space for the file, puts a request to read a
cluster of sample.one in the disk queue, and makes the DiskScheduler ready. Note:
we are assuming that the Shell thread already has access to the client's directory and
therefore can look up the file's directory entry and get the disk location of the first
cluster. If the OS is not maintaining directory information for this client, the Shell
thread must first request a read of the client's directory (to get the file's directory
entry), before trying to read the file. After addressing the command, the Shell thread
uses the Block instruction.
6.
As with the other system tasks, it is not certain when the DiskScheduler thread will
execute; but when it does, it takes the first entry from the disk queue and issues a
command to the disk to perform the appropriate action. The request for client 1.2.3.4
may not be first in the disk queue; in this case, the action for the client is delayed.
The DiskScheduler must block after starting each disk operation.
7.
At some point, the disk completes the read action for a cluster of the file needed by
client 1.2.3.4. It signals this fact with a Device_In interrupt. When OpSys receives
this interrupt, it directs control to the Disk Driver. The Disk Driver must be able to
realize that this interrupt signals the completion of the reading of a file cluster for some
client. The Driver should then make the appropriate thread of Shell ready to deal with
the newly arrived data from the disk.
8.
At some point the Shell thread will be scheduled to execute again for client 1.2.3.4.
The thread must realize that the first cluster is now in memory. It should use this data
to build message packets to be sent to the client. Since a cluster contains up to 2048
bytes of data and a message packet can hold no more than 512 data bytes, the Shell
Jeeves
24 June 2017
System Manual
33
will almost always have to build multiple message packets (fragments) to hold the disk
data; these need to be sent to 1.2.3.4. The packets are placed in the queue for
output through the interface. The Shell thread then makes the Transmitter ready so it
can be scheduled and handle the packets. The Shell thread blocks after generating
the packets from the cluster.
9.
At some point the Transmitter thread will be scheduled to execute. It will take the first
packet on its queue and send it out through the Comm Interface (the packet may be
for any client). Other packets cannot be sent until the Interface completes sending the
current packet. So, the Transmitter thread blocks.
10.
At some point the Comm Interface completes sending a packet to 1.2.3.4 and signals
with a Device_Out interrupt.
When OpSys receives this interrupt, it directs the
response to the Comm Output Driver.
This Driver should then either notify the
Transmitter thread, so the next packet can be sent, or the Shell thread, so the next
disk cluster can be read, or both. If we assume that sample.one has 3072 bytes,
then, the Transmitter would still have three more packets for the client at 1.2.3.4 in its
queue; so, the Driver should make the Transmitter thread ready. If this is the last
packet for the client at 1.2.3.4, the Driver should make the Shell thread ready to deal
with the next cluster. If it is the last packet for the client at 1.2.3.4 and there are
other packets in the queue (from other clients), the Driver should make the Transmitter
thread ready also.
11.
When the Shell thread gets to execute again, it should recognize that it needs to get
the next cluster for the client command (i.e., resume at step #5 above, except that the
same memory may be used as a buffer). When step #11 is reached and the Shell
thread realizes that there are no more clusters to read and no more output for the
client, the thread should construct a prompt message packet for output and make the
Jeeves
24 June 2017
System Manual
34
Transmitter thread ready. The Shell thread also needs to mark the client command as
complete.
There are many administrative details that were omitted in describing this process, such
as verifying that access to the file is allowed, keeping track of how far along the task is,
handling device independence, etc. You must find a way with your OS to allow the system
processes to coordinate their activities when dealing with client commands. Some commands
from the clients can be handled with a single message or disk action; the show command is
described here because it requires multiple coordinated actions and gets four of the six system
processes involved. The 11 steps above are NOT the only way to implement the handling of
the show command; you may see some alternatives as you read it. You are not required to
implement show in exactly this way - you are required only to implement it in a way that
works.
Client Actions
Jeeves is expected to serve two types of clients, those who want Telnet service (this
includes the client at the console) and those who want FTP service. For both of these
services, a client is expected to make a series of requests through a "session". Each session
consists of a series of messages sent from and to the client. Below are sketches of Telnet
and FTP sessions; in each case, the message is described briefly.
Telent
FTP
Client:
Sends SYN
Sends SYN
Server:
Prompts with login please: Prompts with login please:
Client:
Sends username
Sends username
Server:
Prompts with password:
Prompts with password:
Jeeves
24 June 2017
System Manual
35
Client:
Sends password
Sends password
Server:
* Sends prompt Jeeves>
* Sends prompt Jeeves>
Client:
Sends Telnet command
Sends FTP command
Server:
Responds with results
Responds with results
Server:
Repeat at *
Repeat at *
. . . until either
. . . until either
Client:
Sends logout
Server:
Sends FIN with message
Sends quit
Sends FIN with message
or
or
Client:
Sends FIN
Sends FIN
Server:
-- No response --
-- No response --
As you can see, the sessions for the two services are remarkably similar. As a consequence,
your OS should be able to handle both services with a single Shell process to deal with the
commands of the clients. On a real system, there would be separate processes parsing and
implementing the commands; that is, there would be a Telnet Shell and an FTP Shell to deal
with. For Jeeves, you can actually gain a considerable advantage by combining the services
in a single Shell. Also, note that a session can end either by the client logging out (quitting)
or by the client sending a FIN (termination message).
For Jeeves, you may assume that all commands arrive contained in a single message.
Thus, your OS does not need to assemble commands by piecing together parts of several
messages. You may assume that your OS does not need to echo the commands themselves
back to the client; assume that the echoing is being done on the client's local machine. Also,
you may assume that clients do not use typeahead - that is, they do not issue another
command until the previous command is completed and a prompt is sent back. None of these
assumptions could be made on a real server; however, for you to handle these possibilities for
Jeeves, your OS would increase in size by a considerable amount.
Jeeves
24 June 2017
System Manual
36
Telnet Commands
Here is a description of the form of each of the Telnet commands that Telnet clients
(and the console user) are allowed to use. Your OS needs to allow for a few possible errors
on the part of the clients in entering these commands. Your OS is not expected to do fancy
parsing or elaborate error checking. Those errors for which your OS is required to check are
described below. Whenever your OS detects one of these specified errors, it is required to
send the client a specific error message, see the list later.
The system prompt for Jeeves must be
space after the angle bracket.
Jeeves>
where there is one
The OS must send a prompt to each client to indicate
readiness to accept a command; it must be sent prior to every command once the client has
been authenticated.
All Telnet commands are entered in lowercase; there are no command abbreviations;
and the different parts of the command are separated by a single space (or a slash in some
cases). As they appear in the message packets, commands contain a null character after
their end; that is, commands have the form of c-strings. Several commands refer to files;
such references always have the form:
folder/filename
where a slash separates the folder from the filename
There are no implied or current folders; so every file reference must have both parts. There is
only one concession to directory structure - if the client is referring to a file in his/her own
folder (directory), s/he may use a reference such as
substitute for the client's own directory name.
./filename
where the . is a
Thus, for client jwolfe, the reference to
./whatever is the same as the reference jwolfe/whatever
Jeeves
24 June 2017
System Manual
37
Below each of the valid Telnet command forms and their uses are described. Note:
when using the Telnet service, a client cannot enter FTP commands (they should be regarded
as error entries).
access code folder/filename
This command is used to change the access (protection) codes for a file. The command is
restricted to use by the file's owner. Your OS should locate the directory entry for the file and
change its access pairs. The code is a 6-character sequence to specify all three access
pairs. For example, the code RWRWX- indicates that privileged users and the owner both
have full read and write access, while the world has only execute access to the file. Here is
a sample to change a library file: access RWRWX- library/spacy
add userid username password
This command is restricted to use by the root. No other user, privileged or not, may use this
command.
It is used to add another user to the system.
Your OS should encrypt the
password and add an entry to the password file. It should also create a directory entry for the
new user in the users directory/folder, specifying no files. Note: although a new user has no
files, one cluster is allocated to the user's directory to hold directory entries as soon as they
are created.
The userid is a 4-digit number and must be greater than 1000.
The
username may consist of up to eight characters. The password must consist of at least 6
characters with no spaces.
If the userid or username already exists, the OS should send an
error message, rather than add the user. If the password is too short, the OS should also
send an error message. Here is a sample command to add user bozo:
add 3099 bozo theclown
copy folder1/filename1 folder2/filename2
Jeeves
24 June 2017
System Manual
38
This command is used to copy the contents of filename1, which is in folder1, to filename2 in
folder2.
The client must have at least read access to folder1, at least read access to
filename1, and at least create access to folder2 (or write access if filename2 already exists in
folder2). If any of these requirements are not met, your OS should send an appropriate error
message to the client. It should also send an error message if folder1 or filename1 or folder2
do not exist.
example:
If filename2 does exist in folder2, your OS should replace it. Here is an
copy library/spacy ./mine
delete folder/filename
This command is used to get rid of a file. The client must have write access to the folder and
file in order to do a delete. If this requirement is met, your OS should take back the file's
disk storage, remove its directory entry from the folder (rewriting the folder), update the
higher-level directory entry which is for the folder of the file being deleted, and update the bit
map. Here is an example: delete common/mess.txt
list folder
This command is used to provide a listing of the entries in a folder (directory). For each
directory entry, the information to be listed consists of the access pairs, the file size in bytes,
the owner (ID of the user who created the file), the file type, and the filename. The folder
may be a named one or . to mean the owner's folder. Below is a sample listing produced
from the command
list .
RWRW-RWRW-RWRW-RWRW--
given by client wlewis.
3715
3312
23225
677
wlewis
wlewis
wlewis
wlewis
D
P
D
D
simple.one
dosomething
another
tiny.one
Jeeves
24 June 2017
System Manual
39
This listing must be packaged in a message or messages and sent to the client. If the client
is not allowed to access the specified folder, the OS should respond with an error message
rather than a listing.
logout
This command is used to terminate a Telnet session.
Your OS should respond to this
command by sending a FIN message with a logout acknowledgement that looks like this:
End Session at tttttt
where tttttt is the current clock time.
now
This command is used to produce a listing of which clients are currently logged in and what
they are doing. It is sort of a cross between who and ps on Unix or a cross between show
users and show system on VMS.
For each client that is logged in at the time of the
command, your OS should list the client's thread number, IP address, the command currently
being done (or last done), and the client's username. Here is a sample of the command
being given by client richie.
101
102
103
104
144.201.193.179
144. 80.128. 13
24. 43.159.183
24. 77.159. 95
Logging
Valid
list
now
dwagner
wlewis
jwolfe
richie
The extra spaces in the IP address serve to keep the display lined up, also true for the names
of the commands. The command named "Logging" is used as a placeholder for a client who
is still logging in and has not yet been authenticated. The command named "Valid" is used
as a placeholder for a client who has been authenticated but has not yet given any
commands.
Jeeves
24 June 2017
System Manual
40
print folder/filename
This command is used to cause the specified file to be printed. Your OS must use a Shell
thread to copy the file to the spooling area on the disk and then use the Unspooler thread to
print the file. If the folder or the file do not exist or if the client is not allowed access to
either, your OS should respond with an error message, rather than print the file.
remove username
This command is restricted to the root.
No other user, privileged or not, may use this
command. It is used to eliminate a user from the system. Eliminating a user requires that all
of the user's files be removed, that the user's directory entry be removed from the users
directory, that the user's entry in the password file be wiped out, and that the higher-level
directory for the users directory (i.e., the root directory) be adjusted. If the username does
not exist, the OS should send an error message, rather than remove the user.
run folder1/filename1 folder2/filename2 folder3/filename3
This command is used to execute a user program.
Folder1 and filename1 specify the
executable file (containing the program to run). Folder2 and filename2 specify the data input
for the program - this file is read by the executing program. Folder3 and filename3 specify
the output for the program - this file is created by the executing program as it generates
output. Your OS must verify the existence of the files and that the required access is allowed;
it must then manage the execution of the user program - described in a later section.
show folder/filename
This command is used to examine the contents of a file. Your OS should read the file from
disk, package the contents into messages, and send the messages to the client. This must
Jeeves
24 June 2017
System Manual
41
be done one disk cluster at a time (because of requirements on your OS). The OS must
verify the existence of the folder and filename and that read access is allowed.
users
This command is used to produce the complete list of users known to the system. Your OS
should display the userid and username for every user, regardless of whether that user is
logged in. The order is not critical; it is probably easiest to list the users in the order they
appear in the password file. Here is a partial list of what this command produces.
999 root
1013 dcomer
1020 nhorvath
1035 jwolfe
1121 wlewis
FTP Commands
Because FTP has a much more limited purpose than Telnet, there are fewer
commands to contend with.
Nevertheless, the same restrictions on their form and error
checking apply. Also, when using the FTP service, a client cannot enter a Telnet command
(it should be regarded as an error entry). The valid FTP command forms are shown below;
the FTP prompt is also
Jeeves>
dir folder
This command is used to provide a listing of the entries in a folder (directory). For each
directory entry, the information to be listed consists of the access pairs, the file size in bytes,
the owner, the file type, and the filename. The folder may be a named one or . to represent
the owner's folder. Below is a sample listing produced from the command
dir .
given by client wlewis.
Jeeves
24 June 2017
System Manual
RWRW-RWRW-RWRW-RWRW--
3715
3312
23225
677
42
wlewis
wlewis
wlewis
wlewis
D
P
D
D
simple.one
dosomething
another
tiny.one
This listing must be packaged in one or more messages and sent to the client. If the client
is not allowed to access the specified folder, the OS should respond with an error message
rather than a listing (the same error message as would be used for a similar problem on
the Telnet list command).
get folder/filename
This command is used to transfer a copy of a file that resides on the server in the specified
filename of the specified folder to the client. Your OS should verify the existence of the
folder and filename and that access is allowed. The OS should then read the file contents
from the disk, package it into messages, and send them to the client.
put folder/filename
This command is used to transfer a copy of a file from the client to the server and create a
file named filename in the specified folder. The OS should verify the existence of the folder
and its accessibility. The client then sends messages containing the contents of the file being
transferred. To determine roughly how large a file the client may be sending, your OS can
check the total number of fragments in the incoming messages. The client always sends
maximum size fragments, except possibly the last; so if the total fragment count is 6 for
example, the file size must be between 2561 and 3072 bytes. The new file that the OS
creates must have type T to indicate that it was transferred to Jeeves; see the File System
section.
quit
This command is used to terminate an FTP session. The OS should respond to it by sending
Jeeves
24 June 2017
System Manual
43
a FIN message with an acknowledgment message that looks like this:
where tttttt is the current clock time.
End Session at tttttt
Error Messages to Clients
The following situations and error messages are the only parsing and logical errors
that your OS needs to deal with. In each case, a specific error message is shown. Your
OS must use these exact message forms. Do not make up your own messages for these
conditions and do not add messages for situations that you are told are not allowed to
happen.
If a folder is specified as part of a command and that folder does not exist, the OS should
send a message of the form:
Folder does not exist:
dddd
where dddd is the folder's name.
If a folder is specified as part of a command and that folder does exist but the client is not
allowed the required access, the OS should send a message of the form:
Access not allowed to folder:
where dddd is the folder's name.
dddd
If a filename is specified as part of a command and that file is to be used for input or
execution but the file does not exist, the OS should send a message of the form:
File does not exist:
ffff
where ffff is the filename.
If a filename is specified as part of a command and the client is not allowed the required
access, the OS should send a message of the form:
Access not allowed to file:
ffff
where ffff is the filename.
Jeeves
24 June 2017
System Manual
44
If a filename is specified as part of a command and the file is to be used for a purpose that
conflicts with the file's current use by other client(s), the OS should send a message of the
form:
Conflict over file:
ffff
where ffff is the filename.
If on a login attempt, the client cannot be authenticated, the OS should send a message of
the form:
Invalid attempt to login
If on a remove command, the username specified does not exist, the OS should send a
message of the form: No such user:
uuuu
where uuuu is the username.
If on an add command, the username or userid already exists in the password file, the OS
should send a message of the form: Username or ID already exists
If on an add command, the password contains fewer than six characters, the OS should send
a message of the form:
Password is too short
If on an add or remove command, the client is not root, the OS should send a message of
the form:
Command restricted to root
If a command is given that is not one of the listed valid commands, the OS should display a
message of the form: Unknown command:
cccc
where cccc is the given command.
Note about the origin of commands: Commands that come in from remote clients
(Telnet or FTP) are guaranteed to arrive in one packet (message). Each of these commands
ends with a null character; there is no new line character ('\n') at the end of the command.
This was mentioned before. Commands that come in through the console arrive one character
Jeeves
24 June 2017
System Manual
45
at a time, because of the nature of the keyboard; and each such command does end with '\n'
(as the client presses the Enter key). There is no null character entered or attached by the
hardware.
Device Independence
Operating Systems tend to have to deal with a wide range of input and output sources.
The more that the OS can treat every input source like every other input source (and
similarly for output), the simpler things are within the operating system. In your OS, you are
expected to use the idea of device independence in handling the console.
The console
provides command input just as the Comm Interface does, but one character at a time through
the keyboard instead of a command at a time, and without all the header information of a
packet. The console can also receive command output just as the Comm Interface does, but
for display on the screen, rather than transmission to the client; and again no header
information is needed.
The console has a mouse which gives it a third means of input
completely different from keyboard or Comm Interface; however, the mouse is not used in the
current system.
To make input device-independent, some basic level of the OS (generally the device
drivers) must deal with each device's idiosyncracies; but most of the OS should be able to
deal with the input in a generic manner. For Jeeves, your OS is required to make all input
look like it is coming from the Comm Interface. This is not difficult. Collect the keystrokes
as they come in.
When a '\n' is received, indicating the end of a command, take the
collected characters, form a packet that looks like it came thorugh the Comm Interface, place
it in memory where input would normally come from the Comm Interface, and call upon the
Comm Input Driver, as if a Device_In interrupt from the Interface just occurred. From that
point on, the input can be treated as if it had come in from some distant client. The packets
Jeeves
24 June 2017
System Manual
46
that the OS constructs should have Jeeves' IP address as both the source and destination of
the message.
A similar approach can be taken to make output device-independent. Again, the device
drivers must handle the differences; but most of the OS can treat the output generically. So,
when there is output to be sent to the console, Login or Shell can construct output messages
as usual.
When the Transmitter gets the message, it can determine that the output is
destined for the console (if nothing else, by examining the destination IP address) and turn
the content of such messages over to the Screen Driver for display on the screen, instead of
sending the message through the Comm Interface.
There is one tricky point in handling the console in this manner - the console has no
capacity to send a SYN message to get a session started. But then, the console really should
not need to notify the system that it is ready to start a session - it is always ready. From the
time the Bootstrap program finishes and gives the OS control, the console is ready. As part
of the Bootstrap actions, your OS should create a SYN message (with sequence number 1)
for the console and trick the Comm Input Driver into handling it just as described above for
commands. This should lead to Login sending out its "login please: " message to the
screen so that a console user can then start entering username, password, etc.
When a user logs out at the console, a similar situation arises. For remote clients,
your OS should send a final FIN message to terminate the session. But for a client at the
console, after sending the FIN message, the OS must send out another login please: prompt
message to allow the next console user to login. This should be handled by creating another
SYN message as with the first console login. This SYN should also have the sequence
number 1 (it is the start of a new session).
On a system like Unix, device independence is carried much further than you have to
Jeeves
24 June 2017
System Manual
47
go with Jeeves. On Unix, every source of input or output is regarded as file-like and much of
the internal treatment is then standardized to file actions. You would find that trying to do this
with Jeeves would be considerable additional work. Your OS should deal with files using one
set of actions and clients using another.
Dealing with root
The root is a different type of user with more privileges than regular users. It has
already been noted that root is allowed to add and remove users on the system. No other
user is allowed to do that. In addition, root is allowed access to every directory and every file
on the system, as long as root is logged in at the console. When at the console, root is not
bound by any of the access pairs that are used to protect files or directories; root always
passes the access test when at the console.
However, root cannot do absolutely anything. When root is logged in from some place
other than the console, the privileged access pair is used to determine access to a directory or
file. Thus, users can protect their files from a hacker who may guess the root password by
removing priveleged access (setting this access pair to -- instead of the RW default). Also
root, regardless of where it is logged in, must abide by the file use restrictions.
File use restrictions are based on what is happening with a file.
If one client is
currently reading a file (for a show or copy or run or print command), other clients are
allowed to read that same file simultaneously. This is shared reading and is a commonly
provided capability on systems. However, if one client is reading or writing a file, no other
client is allowed to write to or delete that file; not even root is allowed to do this. Writing and
deleting are file actions that require exclusive access; sharing cannot be allowed with such
actions.
If root could get around this file use restriction, the system could be seriously
Jeeves
24 June 2017
System Manual
48
corrupted accidentally. The "Conflict over file:" error message is to be used when one client,
even root, comes into conflict with the file use of another client.
Allowing a privileged user on a system is usually a necessity for system management.
But, the root user can create headaches for you. Because there is a root user, your OS
must provide means for making exceptions for this one user.
It also has to maintain
information that would otherwise not be needed; for example, if root issues the command
list dcomer
then, even though dcomer may not be logged in, the OS must
read in his directory so that the listing can be made. You will find that it may not be easy to
add root capability to your system if you did not plan for it from the beginning. To avoid some
complications that can arise in the simulator and your OS, you are hereby guaranteed that no
script has the root create any additional files in the root directory. (The directory entry for the
root directory appears in two places; this would make updating it awkward.) However, root
may create files in any other directory; it has full access to all directories (at least when it is
logged in at the console).
The only privileged user on Jeeves is root. You are guaranteed that root (the only
user who can) does not add another privileged user to the system. The user ID distinguishes
privileged users from regular users. Any user with a user ID less than 1000 is considered
privileged. Any privileged user has the same access capabilities as root; however, only root
can issue an add or a remove command; and to repeat, the only privileged user is root.
Requirements of Implementation
As you create your OS, you must meet a number of requirements. Failure to meet
these requirements results in severe scoring penalties because alternative implementations
violate the nature of the project; i.e., they are considered cheating.
Jeeves
24 June 2017
System Manual
1.
49
Message packets must be kept in Jeeves' memory. When a packet arrives at the
communications interface, it is stored in memory in association with the Device_In
interrupt. Your OS is not permitted to copy such a packet to some queue that is
contained completely in the OS database (and is therefore separate from Jeeves' 128
KB managed memory).
Doing so would eliminate the
manage-the-buffer-space
element of this project.
The packet must be held in managed memory as the
ProtocolHandler, Login, or Shell system processes act on its contents, although it may
be moved to different portions of managed memory if appropriate. Similarly, when
Login or Shell construct packets for output, they must be held in memory for the
Transmitter process and the Comm Output device driver. You will definitely need
queues or linked lists to keep track of the packets and what element of the system is
working on them. However, it would be awkward to have the queue entry contain the
packet (because the packet must be in managed memory); instead, the entry should
contain a memory reference and packet size or beginning and ending memory
references.
2.
Disk files must be kept on the disk. Your OS may hold in its database copies of
directory information from the disk, i.e., copies of directory entries. However, it is not
allowed to hold copies of files in the database. Each time a client needs to access a
file, your OS must read or write the disk; it may not simply retrieve the information
from somewhere in the database. There is one exception. Your OS is allowed to
maintain a copy of the password file in its database; this will facilitate the response to
the users command for regular clients and the add and remove commands for the
root. However, changes to the password file must be written to disk, even if a copy of
the password information is kept in the database.
3.
Those elements of the disk that are copied into the database must remain faithful
Jeeves
24 June 2017
System Manual
50
copies. That is, if the bitmap, any directory, or the password file change in response
to a client command, your OS must issue update commands to cause the disk copy of
these elements to agree with the changed database copy. This update must be done
as soon as is reasonable after the change to the database. If your OS delays in
doing the update, it may never get a chance; Power_Down may occur at any time.
4.
Your OS must number the processes and threads in accordance with the guidelines
given. System processes must have process ids 1 thru 6; each client session is a
thread and must be numbered, starting at 101. The thread numbered 101 must be the
console session that is begun at Boot_Done. Numbering of threads is sequential; each
client sends a SYN message to initiate the creation of a new thread. User process ids
are required to be numbers greater than 10; each time a user executes a run
command, it should be assigned the next sequential process id (start at 11). Although
each user process is and most system processes are associated with one thread; the
Login and Shell processes may be associated with many different threads as they are
performing their tasks for different clients.
5.
The six system processes must be constructed and used in the manner described
previously. Each must be a void function with no arguments; each must issue a Block
as its last action; each must be called only indirectly by using RunSys.
6.
Your OS must display the client error messages and system prompt as they are given
to you. You are not allowed to make up extra or different messages. The simulator
depends on several of these messages being as given in order to evaluate what is
happening.
If you think you have found some situation different from those with
specified error messages that requires an additional error message, ask about it before
implementing the message.
Usually, the situation will involve something that is
guaranteed not to happen in any script.
Jeeves
24 June 2017
System Manual
7.
51
Your OS must support the execution of user process threads using a model similar to,
if not the same as, the support described in the next section.
User Process Threads
When a client issues a run command, your OS must set up and support the execution
of a user process thread. Each valid run command should cause the OS to create the next
higher numbered process (starting at 11) and associate the client's thread with it. Verifying
that the command is valid requires checking the three files involved.
Setup can probably best be done through the use of the Shell and DiskScheduler.
Start by determining the size of the executable file (in pages); suppose it is N. Assign N+1
page frames to hold the process. Read the N clusters into the first N of the assigned page
frames. The additional page frame holds the data area for the process as it executes. Setup
must also include the assignment of one page frame for the input file and one page frame for
the output file. Setup may include an anticipatory read of the first cluster of the input file; or
this reading may be delayed until the user process actually attempts to read data.
Once the setup is complete, the client thread should be associated with the process;
and that thread should be put in the ready state so it can be selected for execution. During
the thread's execution, it performs three basic types of instructions: 1) "reads" in which the
thread wants to read a record (line) of data from the input file into some variable(s) in the
data area; 2) "writes" in which the thread wants to write a record (line) of variables from its
data area to the output file; and 3) "other" in which the thread is performing some action on
the data it has. The first two of these actions require operating system support; all user
process thread actions on files use sequential access.
Jeeves
24 June 2017
System Manual
52
Reading
Your OS must provide for "reads" by reading clusters into the input page frame as
needed and transferring records from the input file page frame to the data area designated by
the user process. The user process signals that it is reading by causing a User_Pgm_Input
trap, with the R.process.pgmioaddr and R.process.pgmiosize registers set appropriately. The
address that the process provides is a virtual one - it has no idea where your OS has placed
it in memory. The size that the process provides is a maximum - it cannot know the actual
size of the next input file record. (There will never be an instance in which the specified size
is too small.) The OS must maintain a file pointer so that it knows where reading left off in
the input file page; and, from that point, copy the bytes of the next record (up to the \n) to
the physical address which corresponds to the virtual address that the process specified (and
update the file pointer).
It may be that when a "read" is requested, that there is no data in the input page
frame (as before execution begins) or that there is only part of a record left in the input page
frame (the rest of the record is in the next cluster). In both of these cases, the OS must
suspend execution of the thread while it uses the DiskScheduler to read the next input file
cluster into the input page frame. During the time that it takes to fetch the file cluster, the
thread should be put in a "waiting" state. When the cluster read is finished, the OS must
copy the record (or what remains of it) to the user process' data area. The thread can then
be made ready again for execution.
There is one complication with supporting reading. The OS must always be aware of
the size of the input file. If the user process attempts to read beyond the last record of the
input file, it must be stopped. This is normal end-of-file processing for operating systems.
Your OS must terminate any thread which tries to read beyond the end of file.
Jeeves
24 June 2017
System Manual
53
Writing
Your OS must support writing by transferring records from the thread's data area to the
output page frame; and when the page frame becomes full, writing the page frame as a
cluster to the output file. A user process signals a "write" by using a User_Pgm_Output trap
with registers R.process.pgmioaddr and R.process.pgmiosize set appropriately. The address
refers to the virtual address of the beginning of the output record; the size is the actual
number of bytes in the record (including the \n). The OS must maintain a file pointer to the
output page frame so that it knows where the data at the implied physical address should be
transferred to in the output page frame. If there is enough space in the page frame, the OS
must copy the data bytes (including the \n) to the page frame and update its file pointer. If
there is not enough space, the OS must fill the buffer with part of the data record and initiate
a disk transfer through the DiskScheduler.
When a disk write is needed, the OS must put the thread in a "waiting" state until the
disk operation is complete, obtain a free disk cluster, and update the output file's directory
entry (the in-memory copy). When the transfer is complete, if more of the data record needs
to be copied, the OS must move the partial record into the beginning of the output page
frame, update the file pointer, and make the thread "ready" again. You are guaranteed that
no user process thread will write more records than can fit into a file
Time Out
You are encouraged to use time slicing to give all threads a fair chance at using the
CPU. The time slicing technique is simple to describe: each time a user thread is selected to
execute, set R.timer to a future time at which it must give up use of the CPU. When that time
is reached, a Time_Out interrupt is generated. Your OS should respond to this interrupt by
Jeeves
24 June 2017
System Manual
54
trying to select a different thread from those that are ready (and putting the one that was
executing into a "ready" state).
In practice, there a few complications involved in time slicing. Your OS must turn the
timer off, if the executing user thread is stopped by some interrupt other than Time_Out. For
instance, if a message packet arrives from another client, the Device_In interrupt stops the
executing user thread. To execute the ProtocolHandler and deal with the packet, the user
thread must be made "ready" and the ProtocolHandler must be scheduled. If the timer is not
turned off, a Time_Out interrupt will occur at some later time when the user thread may not
even be running. If the user thread is not moved to "ready" and some other thread selected
to execute, there may be long delays in responding to some interrupts. Also, when a user
input or output trap occurs, the OS must decide whether or not to stop the timer. If the
request can be satisfied by just accessing the buffer, the user thread can be resumed and
there is no need to stop the timer. If the request leads to disk access, the timer needs to be
stopped because the user thread must be put into a "waiting" state.
Termination
When a user process thread terminates, the OS actions are the same, regardless of
the reason for termination (there are three possible reasons: User_Terminate, User_Abort, or
forced termination for reading too far).
The actions are 1) recover the memory space
allocated for running the process and for the input file page frame; 2) finish the writing of the
output file - the output page frame may be partially full; it must be written; it
is also
necessary to update the directory holding the file and the directory a level above; recover the
memory space being used for these disk transfers (all this can be referred to as closing the
output file); 3) close the input file - much easier; 4) remove the process and re-associate
the thread with Shell; and 5) prompt the user.
Jeeves
24 June 2017
System Manual
55
File System
The file system is designed to use the disk in clusters (4 sectors at a time). As with
any system, the starting point is the boot record (located in the cluster starting at surface 0,
track 0, sector 0 - from now on abbreviated as (0,0,0) and called a disk location or diskloc).
The boot record has the following layout.
Boot Record
Size (bytes) Form
12
Contents
char
Instruction to start bootstrap program
4
long
Number of surfaces on this disk
4
long
Number of tracks per surface
4
long
Number of sectors per track
4
long
Sector size in bytes
4
long
Cluster size in sectors
3
diskloc Disk location (surface, track and sector as three unsigned chars) of
cluster containing the bit map
3
diskloc Location of the cluster containing the root directory
3
diskloc Location of the cluster where the kernel begins
6
diskloc Locations of the starting and ending clusters of the spooling area the spooling area is all of surface 4.
6
diskloc Locations of the starting and ending clusters of the swapping area the swapping area is all of surface 5.
1992
Bitmap
char
Bootstrap program
Jeeves
24 June 2017
System Manual
56
The bitmap and disk usage information are kept in a cluster whose disk location is
specified in the boot record. This cluster has the following form:
Size
768
Form
Contents
char
Bitmap - a [6][128] array of char, where each bit of a char
represents the availability of one of the 8 clusters in a track.
The bit usage is as follows: with bits numbered 76543210,
bit n represents sectors 4*n through 4*n+3. A 1 in a bit
position indicates the cluster is in use; a 0 indicates the cluster
is free. Example: if bit 2 is 1, sectors 8-11 are in use.
3
diskloc Location of the last cluster used by the file system, excluding the
kernel and daemons storage which are at the far end of the
file space.
1277
char
Wasted space.
Root Directory
The root directory is kept in a cluster whose disk location is specified in the boot
record.
The disk location for the root directory must stay the same throughout each
simulation. This cluster holds the directory entries of the root user. Each directory entry
consists of 128 bytes in the following form. Because clusters hold 2048 bytes, each cluster
of a directory can hold up to 16 directory entries.
Size
Form
Contents
28
char
File/Directory name - up to 27 characters plus null terminator,
file/directory names are not allowed to contain any white
space characters or the symbol slash (/)
Jeeves
24 June 2017
System Manual
57
4
long
Number of bytes the file/directory occupies
4
long
Number of logical records in the file/directory - for a directory,
each record is a directory entry; for a data file, each record is
a line of data; for a program, each record is an instruction; for
a transfer file, each byte is a record.
6
accesspair
An array of three pairs of characters to specify what access is
allowed to the file/directory. The first accesspair indicates
"Privileged" access, controlling what access privileged users
have to this file/directory from non-console locations. If the
first character of the pair (input access) is R, reading, listing
and executing are allowed; if it is X, executing only is allowed;
and if it is -, no input action is allowed. If the second
character (output access) is W, updating, appending, creating
and deleting are allowed; if it is C, creating only is allowed;
and if it is -, no output action is allowed. The second
accesspair indicates "Owner" access using the same codes;
this pair controls what access the file's owner has. The third
pair indicates "World" access - what access all other users
have. Only the owner of a file/directory can change the
access.
1
char
Type of file: F (Folder/directory), P (Program), D (Data), or
T (Transfer) - only from FTP.
9
char
Null terminated name of the user who owns the file/directory.
1
char
The character * always - used by the disk utility program and
the simulator.
3
72
char
Wasted space.
diskloc An array of 24 disk locations referring to the clusters that hold the
contents of the file/directory. Unused locations may contain
Jeeves
24 June 2017
System Manual
58
garbage. For files of fewer than 24 disk locations, the first n
entries must be used, where n is determined by the size of the
file.
There are 7 directory entries in the root directory.
These directory entries are
associated with the following folders/directories and files.
root
Root directory's own directory entry.
That is, the root directory contains a
directory entry of the root directory itself.
kernel
The central part of the operating system, stored as a program file.
daemons
The auxiliary part of the operating system, stored as a program file.
password
A special data file containing the encrypted user passwords and user
identification numbers.
library
A directory meant to hold files that users can access for reading or executing.
All files should have "World" access set to R- when they are created (with
privileged user and owner access set to RW). The files here are not meant to
be changed or deleted; however, new files may be added to the directory by
anyone and the owner can change the access on any file s/he has created.
The access to the library itself is RWRWRC to allow anyone to use the files
that are there and to create new files in the library. For any file created in the
library directory, the accesspairs should be RWRWR- The owner of new library
files can change the access.
common
A directory meant to allow users to share files in any way they wish. All files
should have all access pairs set to RW when they are created to allow any
user to do anything s/he wishes to any file. The access may be changed later
by the file's owner.
users
The directory for the users. Each user (including root) has a directory entry in
this directory.
The directory entry for user root is identical to the root
Jeeves
24 June 2017
System Manual
59
directory's directory entry for itself. Only the root gets this special treatment.
Password File
The password file contains data in a format that is different from all other data files.
Its contents are coordinated with the user directory. The order of the users in the users
directory should match the order of the password file entries; however, this is not an absolute
requirement. Each password entry has the following form:
Size
Form
Contents
4
long
User Identification Number - unique for each user, assigned at
the time the user is added to the system.
9
char
User's name stored as a null terminated string of up to 8
characters (plus null).
19
char
This user's encrypted password stored as a null terminated cstring 17 characters long (plus null).
Data Files
All files on the original disk (as well as all files that can be created using Telnet
commands) are either normal data files or program files. One FTP command (put) can
create a data file on the disk that does not have normal data file form. Normal data files
contain ASCII characters arranged into records. Each record ends with a '\n' (new line
character); the records all have a similar format but vary widely in their length. The format of
a data record is as follows:
folder filename nnn sssdata
Jeeves
24 June 2017
System Manual
60
That is, a folder name, a space, a file name, a space, a three-digit record number (nnn), a
space, a three-digit record length (sss) and the data characters of the record. The data
characters are simply the alphabet, repeated as often as necessary. The sss value is the
number of alphabet letters that appear; this does not count the folder, filename, record number
and spaces. Each record ends with a '\n' character; this character is not counted as part of
the record length (sss) either. Here are records 5-7 from file tiny.one in the wlewis folder to
illustrate
wlewis tiny.one 005 036ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
wlewis tiny.one 006 040ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN
wlewis tiny.one 007 007ABCDEFG
The FTP command put can transfer a text file of almost any form to a Jeeves file.
Such files should be flagged as different by making the data type in the directory entry be T,
for 'transfer' and the number of logical records for the file should be made equal to the
number of bytes in the file. Transfer files can be subsequently copied or printed but not used
as data for program executions or displayed with the show command.
Program files contain instructions, each 4 bytes long. Consequently, the number of
logical records is always 1/4 of the number of bytes in the file (each instruction is a record).
An instruction contains an act value (one byte) indicating the operation to perform, an elapse
value (one byte) that is used by the simulator, and a reladdr value (two bytes) indicating the
relative address of the data that the instruction acts on. Generally, the OS need not be
concerned about these instructions.
Miscellaneous Thoughts about the File System
Overall, the file system can be thought of as being in four levels: 1) the Boot Record
Jeeves
24 June 2017
System Manual
61
holds the location of the root directory and bit map (as well as specifications about use and
structure of the disk); 2) the Root Directory holds directory entries for the three key directories
used by clients (users, common, and library) and entries for the operating system and
password files; 3) the Users Directory holds one directory entry for each valid client of the
system; and 4) each client directory holds the directory entries for that client's files. Your OS
must maintain some semblance of this structure internally (in its database) so it can make
changes, find things, etc.
Although the bitmap, root directory and the other standard directories and files are at
predetermined places on the disk, your OS is expected to read the boot record and extract the
necessary disk locations, rather than using your personal knowledge of where the appropriate
clusters are and simply reading them in directly. The sample program (shown later) partly
illustrates this as it reads the root directory and the user directory.
Because each directory entry occupies 128 bytes, it is possible to keep track of 16 files
in one cluster of a directory. Although all directories initially have fewer than 16 files in them,
your OS should allow the users directory (at least) to have more than 16 files. The directory
entry for a directory, just like a directory entry for a file has space for 24 disk locations.
Thus, it is possible for a directory to hold entries for 384 files. Each directory entry for a file
can refer to 24 clusters of disk storage, for a total size of 48 KB. Some files are near
maximum in size (e.g. kernel file or the daemons file); others are very small, occupying less
than one cluster.
Your OS is allowed to maintain in its database a copy of the bit map, a copy of the
root directory, copies of the users directory, library directory and common directory, and a
copy of a user's directory for every user. These copies may be used for reference when
responding to user commands; however, they MUST remain faithful copies. So, if some
action causes the bit map or the root directory or the users directory or a client's directory to
Jeeves
24 June 2017
System Manual
62
change, your OS MUST update both the database copy and the disk copy. Failure to do this
will have catastrophic consequences when running your OS - the simulator is evaluating the
actions your OS takes; it cannot access your OS database; it can access only the disk to
determine if actions have been done correctly. If the disk is not updated, the simulator does
not have the same view of the file system as your OS might. This can lead the simulator to
report bogus error messages or even to crash.
Unrealistic Things The Simulator Does
The simulator is pretending to be a the hardware of a real server system. However, in
a variety of ways, the simulator does not behave as real server would. Partly, this is because
the environment that the simulator exists in is not completely realistic. Below is a list of some
of the ways in which a real server system would be different.
1.
A real server would have to deal with all seven OSI layers or, at least, the four
complete TCP/IP layers. In this discussion, OSI layers are referenced with TCP/IP
layers in parentheses.
By simplifying the data link and physical layers (network
interface layer), the issues of actually dealing with the hardware have been glossed
over so that a few registers are all that is needed to initiate message transmission and
reception. The Ethernet protocol at the data link layer is ignored completely. The
elements of retransmission of lost messages and construction of messages from
piecemeal datagrams that may possibly be out of order would be the job of the
network layer (Internet layer). That task is completely done away with by having
message packets contain whole commands and never arrive out of order or requiring
retransmission. Layers (application) above the transport layer have been eliminated by
keeping the services basic and similar, so that a single Login process and Shell
process can easily deal with the incoming messages.
Many of the complications
Jeeves
24 June 2017
System Manual
63
associated with TCP/IP are eliminated by simplifying the IP and TCP headers and
cutting down on the types of message interactions. Also, the IP addresses are all
treated as class B even though there is no enforcement of the requirement that the
network ID begins with 10.
2.
The clock on the server is extraordinarily slow in comparison to many of the other
system components. For the most part, you should not notice this. The primary
reasons for the slow clock (ticking each 10 microseconds) are to allow the simulator to
work with reasonable numbers in trying to sequence the activities (interrupts) that it is
generating and to keep the executing user programs small.
3.
The simulated clients make only very limited types of errors in the commands they
enter. Real clients could screw up in a many, many other ways. The types of errors
that your OS must handle are kept restricted so that you do not need to make a
complicated parsing element for the Shell. This is a course in operating systems, not
command languages; so parsing of the commands is deliberately kept simple.
4.
Supervisor mode is used far too much on Jeeves. A real server would greatly restrict
the use of this mode because interrupts cannot occur when the system is in this mode.
We will discuss in class what happens when the various components of the operating
system run in user mode and what it would take to prevent the system processes from
conflicting with each other. But for you to implement an OS which allows interrupts
while the system processes are running, a great many elements (semaphores or
monitors or their equivalent) would need to be added. Also, the simulator would have
to have a more complicated structure.
5.
The scheduling of threads to use the CPU is slightly different from the way this would
be handled on a real system. Real systems commonly have many processes with
Jeeves
24 June 2017
System Manual
64
multiple threads, even allowing all processes to have multiple threads. Also, there
would be no need to maintain thread numbers across processes; instead, threads
would be relative to the process. This level of sophistication would create too many
headaches for you and would make the simulators monitoring job much more difficult.
6.
The file system that you are required to use is rather crude. Real systems today
permit clients to create subdirectories and links, as well as having much larger files
with much more complicated directory entries than Jeeves allows. But, if all that is
allowed, the task of maintaining the file system grows enormously.
7.
There are no execution stacks.
User programs are not modular, do not include
function calls; so that argument passing and return addresses need not be stored.
Also, by not allowing interrupts in supervisor mode, it is not necessary to save and
restore state information about OS actions.
Guarantees
To prevent you from trying to do unnecessary tasks in your OS, the following list of
guarantees are provided. For the most part, those things which are not allowed to happen are
prevented from happening because they would put more of a burden on you the OS designer;
and this burden is considered greater that the benefit of letting you experience a more realistic
situation. Because of these guarantees, some elements that you might think you need in your
OS are not needed. You are guaranteed that . . .
1.
There are no syntax errors in the commands coming from clients. No omission of
fields, no extra fields, no invalid numbers, no messed up file specifications.
simulated clients are better at typing than you are.
The
Jeeves
24 June 2017
System Manual
2.
65
There is no need to worry about running out of disk space. Created files will not
exceed file storage.
Spooled files do not exceed the size of the spooled area,
provided your OS actually prints the spooled files and recycles the space.
3.
There is no need to worry about running out of memory, provided you recycle. At no
time do the clients who are logged in need more memory than what should be
available.
4.
There is only one privileged user, root.
5.
There is no time in any script when more than 12 clients are logged in at the same
time.
6.
If the printer becomes disabled, it will always become enabled again and with enough
time for a reasonable OS to get all of the spooled files printed before the Power_Down
occurs.
7.
No user attempts to log in on Jeeves until at least two seconds (200000 ticks) into
the simulation. Thus, there is plenty of time for your OS to get itself set up before the
users start doing anything.
8.
No user has more than 30 files in his/her directory at any time during a simulation.
9.
No new directories or files are added to the root directory. root always contains seven
entries, although the content of those entries may change.
10.
No hackers attempts to send Jeeves trick packets to try to confuse it or overload it
Jeeves
24 June 2017
System Manual
during a simulation.
66
However, some packets not intended for Jeeves are sent to
Jeeves because it is on a network with other servers.
11.
No user program attempts to read anything but a data file.
12.
No client gives a show command for anything but a data file. However, it is perfectly
reasonable to use copy or get or delete on any type of file; and it is reasonable to use
a print command for a data or a transfer file.
13.
No client gives a run command to execute anything but a program file.
14.
No more than 20 files are open at any one time by any script.
15.
There is no need to echo the commands back to the client. In fact, doing this causes
redundant output in various simulator log files.
16.
Although all clients are allowed to use either Telnet or FTP services, any client who
logs in at the console uses only Telnet.
17.
No more than 64 valid users can exist at any one time.
18.
At no time does root attempt to remove any user who is currently logged in.
19.
No more than one client tries to start a session from one IP address at a time.
However, one client may simultaneously start sessions from separate IP addresses;
and multiple clients may have sessions sequentially from the same IP address.
20.
No data file record in any data file is longer than 150 bytes.
Jeeves
24 June 2017
System Manual
21.
67
No user process thread outputs more records that can fit in a file; and every input
request from a user process thread specifies a size of 150.
22.
Provided the OS does reasonable processing of client commands, no client uses
command typeahead - entry of a second command before the first is finished and a
prompt is received.
23.
The only bogus messages that Jeeves receives are SYN messages directed to other
servers on the LAN. There are no PSH, FIN, or ACK messages that are bogus.
Auxiliary Simulator Functions
In addition to simulating the Jeeves hardware, the simulator provides many other
capabilities to the operating system writer, you. It generates a wide variety of outputs, some
of which are always produced, and others which are produced for the asking. If you use this
output wisely, it can greatly aid you in debugging your OS. It also provides proof that your
OS did indeed serve the clients by directing Jeeves in doing the tasks they requested.
Every time you execute your OS with the Jeeves simulator, it produces results in five
files, jeeves.log, jeeves.report, printer.log, execution.log and xxx.final. jeeves.log records
every input or output transfer that is performed during a simulation and shows the time and
associated device for the transfer. jeeves.report is a summary of all of the simulation activity.
printer.log captures all output to the printer.
execution.log records, approximately, the
records input and output by user programs.
xxx.final holds the disk image after the
simulation, assuming xxx is the starting disk image.
Jeeves
24 June 2017
System Manual
68
jeeves.log
The jeeves.log file shows in chronological order all the significant events of the
simulation, with considerable detail. If the script is complicated, this file can be quite long.
Below are two segments of a jeeves.log file to illustrate.
481034
Message:
557345
Message:
557383
Message:
557391
Message:
627757
Message:
628609
Begins:
628678
Message:
628712
Message:
628731
Message:
1914262
2339604
2340344
2340438
Comm Out IP: 123.123.123.123 DL: 21 Fg: 0 FT: 0 Ty: A Srv: T Seq: 4
Jeeves> .
Comm In IP: 123.123.123.123 DL: 18 Fg: 0 FT: 0 Ty: P Srv: T Seq: 5
users.
Comm Out IP: 123.123.123.123 DL: 164 Fg: 0 FT: 0 Ty: P Srv: T Seq: 5
999 root\n1013 dcomer\n1020 nhorvath\n1035 jwolfe\n1121 wl
Comm Out IP: 123.123.123.123 DL: 21 Fg: 0 FT: 0 Ty: A Srv: T Seq: 5
Jeeves> .
Comm In IP: 123.123.123.123 DL: 28 Fg: 0 FT: 0 Ty: P Srv: T Seq: 6
show ./tiny.one.
Disk R Cluster: (0,5,20) Address: 40960
wlewis tiny.one 001 024ABCDEFGHIJKLMNOPQRSTUVWX\nwlewis tiny.
Comm Out IP: 123.123.123.123 DL: 524 Fg: 1 FT: 2 Ty: P Srv: T Seq: 6
wlewis tiny.one 001 024ABCDEFGHIJKLMNOPQRSTUVWX\nwlewis tiny.
Comm Out IP: 123.123.123.123 DL: 177 Fg: 2 FT: 2 Ty: P Srv: T Seq: 6
JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK\nwlewi
Comm Out IP: 123.123.123.123 DL: 21 Fg: 0 FT: 0 Ty: A Srv: T Seq: 6
Jeeves> .
Screen: Jeeves>
Keyboard In: list library
Screen: RWRWR1752
jwolfe
Screen: Jeeves>
P
helper\nRWRWR-
21538
dcomer
Each transfer begins with the details of the device involved in the transfer. On the first
line, we can see the time (481034) of an output message sent to IP 123.123.123.123. The
IP header data length (DL) is 21 (12 for the TCP header, 9 for the text); it is fragment (Fg)
0 of a total fragment count (FT) of 0; it is message type (Ty) A for ACK, using service (Srv)
T for Telnet; and it is message sequence (Seq) number 4. The content of the message
appears on the next line, Jeeves> the system prompt. (The . is the null character after the
text; it is counted in determining data length.) The second transfer is an input at the Comm
Interface (it is a users command).
The third transfer is only partly shown.
For long
messages (the third one has a data length of 164 bytes), only the first 60 bytes are shown.
Jeeves
24 June 2017
System Manual
69
This is the way all large transfers are handled in the log; only the first 60 characters are
shown. Note that the newline character is shown as \n rather than allowing it to output
normally and cause movement to the next line. This approach keeps the messages more
compact, although it does not show multi-line messages as they would appear to the client.
The sixth transfer shown (at time 628609) involves the disk. For disk transfers, the
log shows the action (R for read, W for write), the cluster number (0,5,20) and the memory
address (40960) used for the disk transfer. From the fifth transfer message, we can see that
the disk was being read in order to perform a show command (show ./tiny.one).
Following the disk information for the sixth transfer, we see the first 60 characters that were
read from surface 0, track 5, sector 20. tiny.one is a very small file; its contents can be sent
to the client in just two packets.
The next two transfers show the output messages for the show command. Note the
values of DL, Fg, FT and Seq for these messages. The seventh message is the maximum
allowable length (DL is 524); it is the first (Fg=1) of two fragments (FT=2) that are being
sent in response to the incoming message with sequence number 6 (Seq).
The eighth
message is the second fragment. From this information alone, it is possible to infer that
tiny.one contains 677 bytes (524 - 12 + 177 - 12). The 12's are subtracted for the TCP
headers that are part of each message.
The ninth transfer shown also uses sequence number 6. This is the prompt message
after completing the show command. So, it is regarded as being part of the response to
incoming message 6 which contained that command.
Note the message types (Ty values) being used.
Incoming client messages are
PSHes, as should be expected. Outgoing messages are either ACKs or PSHes. The OS that
was executing here uses ACKs for sending prompts and PSHes for other packets sent to the
Jeeves
24 June 2017
System Manual
70
client. You may choose whether or not to adopt this strategy in your OS; however, this is the
recommended approach.
In the second segment from jeeves.log, we can see transfers involving the console.
Less information is necessary to show these transfers; so, one line is used for each transfer.
Transfers to the screen show only the clock time, the word "Screen:", and the first 60
characters of the transfer (fewer if there are fewer than 60 in the transfer). Transfers from
the keyboard show only the clock time, the words "Keyboard In:", and the characters that
came in as a command.
Null characters are not shown as '.' for either input from the
keyboard or output to the screen.
Note:
if there are any simulator reported errors, they are also recorded in the
jeeves.log file.
jeeves.report
The jeeves.report file is a summary of everything that occurs during a simulation. The
report is divided into several sections, most of which simply show the number of times
something happened. The report gives the big picture of how your OS responded to the script
it was presented. The first section of the report shows the activity on each of the devices.
Here is a sample.
Status
0
7
21
0
7
0
Clear
0
0
16
26
0
0
Outputs
0
0
20
0
7
0
Inputs
0
7
16
26
0
0
Errors
0
0
0
0
0
0
Device
Mouse
Disk
Comm
Keyboard
Screen
Printer
Jeeves
24 June 2017
System Manual
71
The first column shows the number of times the GetStatus instruction was performed on each
device. The second column shows the number of times the Clear command was performed
on each device. The third shows the number of StartActs for output issued to each device
(here disk seeks and printer ejects are considered output actions). The fourth shows the
number of inputs from each device - this includes StartActs for the disk or keystrokes for the
keyboard or incoming messages for the Comm Interface or spontaneous actions for the
mouse. The fifth shows the number of errors associated with each device - it is good to have
zeros in this column.
The second section of the report collects information about each IP address which was
dealt with. Again, the information is tabular. Here is a sample.
IP
SYN
24. 77.159. 95
1
24. 43.159.183
1
144. 80.128. 13
1
144.201.193.179
1
For other servers
0
ACK
3
4
3
5
PSH
5
7
5
4
FIN
1
1
1
1
Srv
T
T
T
T
The IP addresses are listed in the reverse order in which they were a part of the simulation,
i.e., 24.77.159.95 was the last IP address to be heard from. The table shows the number of
SYN messages, ACK messages, PSH messages, and FIN messages for each IP. In this
case, each IP had one client in the simulation so there is a single SYN and a single FIN.
ACKs are generally from prompt messages; PSHes are generally from data messages. Srv
indicates the service; in this case, all clients were using Telnet (T). Note that even the
console is shown here - Jeeves' IP address, 144.201.193.179, represents the console and the
messages were all used internally to provide device independence. The last line referring to
"other servers" is a count of messages that Jeeves received which were intended for other
servers.
Jeeves
24 June 2017
System Manual
72
The third section is about what each client did. Here is a sample.
Username
--richie
jwolfe
wlewis
dwagner
IP
144.201.193.179
24. 77.159. 95
24. 43.159.183
144. 80.128. 13
144.201.193.179
Thread Srv Pkts Cmds
105 T
1
-2
104 T
5
2
103 T
6
3
102 T
5
2
101 T
5
2
Login
911638
220016
210015
200011
0
End Session
-1
522640
601947
497131
911384
Again, the listing is in reverse chronological order based on login time. For each client, we
see the client's username, the IP address they used, the thread number that was assigned to
the client, the service used (here, all Telnet - T), the number of packets that were exchanged
between Jeeves and this client, the number of commands the client entered, the clock time
when the client logged in (sent SYN really), and the clock time when the client logged out.
Note that dwagner logged in at the console and when he logged out, no one else logged in.
This is why two clients are shown for the console IP; and the last one (at the top) is "---"
which is used as a placeholder until a client logs in. The fact that the console was unused
after dwagner logged out also causes the unusual command count and End Session time for
the top entry.
The section about user process thread executions may come next.
This section
appears only if the script contains run commands and the operating system supports those
commands. Here is a sample from a script containing two run commands.
Execution
102a
103a
Inputs
25
15
Outputs
50
45
TimeOuts
10
15
Stops
3
4
End
T
A
Start
413635
416955
Finish
513033
525841
The execution designator identifies the thread (e.g. 102) and the number of executions ('a'
indicates the first run command for thread 102; 'b' would indicate the second, and so on).
The number of inputs and outputs refer to the executing program's requests. The number of
time outs depends on the time slicing. Stops are caused by interrupts that are unrelated to
Jeeves
24 June 2017
System Manual
73
the program which occur during execution. The "End" letter indicates termination (T), aborted
(A), or unfinished or forced to terminate (?). The execution times are also shown.
The next section shows the number of privileged instructions, the number of interrupts
and the number of times that system processes were scheduled. Here again is a sample.
Count Interrupt/Trap
1
Boot_Done
1
Power_Down
25
Device_In
31
Device_Out
0
Device_Enable
0 Device_Disable
0
Control_Done
92
Block_Self
0
Time_Out
0 User_Pgm_Input
0 User_Pgm_Output
0 User_Terminate
0
User_Abort
150
TOTALS
Count
46
12
44
92
57
92
0
1
344
Instruction
GetStatus
Clear
StartAct
Block
Wait
RunSys
RunUser
Halt
TOTALS
Count System Process
26
DiskScheduler
13 ProtocolHandler
4
Login
31
Shell
0
Unspooler
18
Transmitter
92
TOTALS
These are straightforward counts of how many times each thing occurred. A few examples:
the RunSys instruction was used 92 times and each of those times Block was used - this is
good. A thread of Shell was scheduled 31 times to deal with pending commands. There
were a total of 31 Device_Out interrupts with 44 StartAct instructions. There were 13 disk
input operations to account for the difference between the Device_Out count and the StartAct
count - each disk input is also preceded by a StartAct.
After the counts, there may be a dump of the bit map from the disk. This may be
followed by a dump of the directory entries in the root directory and the users directory.
These dumps appear only if there were write actions on the disk; they show how the disk has
changed.
printer.log
Jeeves
24 June 2017
System Manual
74
This file contains the output that has been sent to the printer, in the order and form it
was sent. If your OS does a paper eject, as it should, when the printing of a file is finished,
an "ejection marker" is output at the end of the file. The ejection marker is simply a line of
dashes with the word "Eject" and a time embedded in it; this separates the end of one file
from the beginning of the next. If Printer Disables and Enables occur, these are also noted in
the printer.log file. Below is a sample from a printer.log file showing the beginning of printing
of the term.paper file from the library directory.
Printer Log based on script print2.scr with disk newfiles
450897
library term.paper
CDEFGHI
library term.paper
CD
library term.paper
CDEFGHIJKLMNOPQRS
library term.paper
001 061ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
002 056ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
003 071ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB
004 036ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ
The number at the beginning (450897) is the clock time when the following lines from the
printer buffer begin printing on paper. Only part of the printer buffer contents are shown.
Note that whole output lines are recorded in the log file, not just the first 60 characters.
execution.log
This file contains all or part of each input or output record read or written by any user
program that runs. Each program input is recorded as an introductory line to state the time,
the thread and address involved followed by a line containing up to 75 characters from the
input record. Each program output is recorded as an introductory line to state the time, the
thread and address involved, followed by a line containing up to 75 characters from the output
record. Input records are logged in a delayed fashion (to allow the OS to get information
into memory); output records are logged at the time of the trap. Below is a sample of the
Jeeves
24 June 2017
System Manual
75
beginning of an execution.log file.
416941 Input to thread 102 at physical address 44575
jwolfe my-first-data-file 001 059ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
417553 Output from thread 102 at physical address 44754
jwolfe THREAD.102a 007 055ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
418332 Output from thread 102 at physical address 44671
jwolfe THREAD.102a 008 070ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW
418378 Input to thread 102 at physical address 43631
jwolfe my-first-data-file 002 079ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP
421062 Output from thread 102 at physical address 44380
jwolfe THREAD.102a 009 015ABCDEFGHIJKLMNO
Time out for process 102 at 422546
424478 Output from thread 102 at physical address 44672
jwolfe THREAD.102a 010 016ABCDEFGHIJKLMNOP
Notice the filename part of the output records. The simulator generates all program output;
but the simulator has no easy way of determining the name of the file being written.
Consequently, the simulator puts in place of the filename a name composed of the letters
"THREAD", the thread number (102 in this case), and a sequencing letter ("a" in this case).
The sequencing letter for a second file created by thread 102 would be "b". Also, note that
Time_Out interrupts are logged in the execution log - see the second to last line.
xxx.final
After the simulation is complete, the simulator copies the contents of the disk to a new
file. Because the simulation can be done with a disk file having any name, the simulator
records the final disk image in a file whose name is derived from the original disk file; it is not
really named xxx.final. So, if the simulation was started on a disk file named thedisk, the
final image will be written to a disk file named thedisk.final
Tracing Events
In addition to the jeeves.log file and the jeeves.report file, the simulator can also
Jeeves
24 June 2017
System Manual
76
display other information about what is going on, if you ask for this information. The way to
ask is by specifying one or more trace variable values in a file called trace.setup
There are
nine trace variables; all but one are integers. The idea is that the simulator examines these
variables at key points in the simulation and if the variables have a appropriate value, some
key piece of information is displayed (on the screen in front of you). This display (a trace)
can show you a great deal about how far the simulation went before something went wrong.
It often indicates exactly what it is that went wrong.
When a simulation begins, the simulator looks for a trace.setup file, if none is found,
the trace variables are set to their default values which cause no information to be displayed.
If the file is found, the simulator reads in the nine values for each of the trace variables and
uses the values you have specified to control the display. The nine values must be in the
order shown below, each value separated from the next by whitespace.
Following is a
description of each variable.
T.icode
For tracing interrupts and traps. When this variable is set to a non-default
value, the simulator displays information about the specified interrupts or traps
just BEFORE they occur, i.e., just before OpSys gets to act on them. The
value in T.icode uses one bit for each interrupt or trap, like this
------------------------------------------------. . . | |13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1|
------------------------------------------------So, to get a display for interrupt code 1, you must set the rightmost bit of
T.icode to 1; for interrupt code 2, set the next to rightmost bit and so on for
each of the interrupt codes. You may set T.icode to trace any combination of
interrupts or traps in this way. Here is a practical example; set T.icode to 12
(which in binary is 000000001100) thereby requesting a trace for all
Device_In (3) and all Device_Out (4) interrupts. If you set T.icode to 0, ALL
interrupts are traced - be careful when doing this except for very simple scripts;
Jeeves
24 June 2017
System Manual
77
you may get a lot of output. The default value for T.icode is -1.
T.instruction For tracing privileged instructions. When this variable is set to a non-default
value, the simulator displays information about each of the specified privileged
instruction uses, usually right at the end of the privileged instruction.
T.instruction uses one bit for each instruction, like this
--------------------------------------. . .| | | |Ht|RU|RS|Wt|Bl|SA|Cl|GS|
--------------------------------------So, to display information about GetStatus (GS), set the rightmost bit; to
display information about Clear (Cl), set the next to rightmost bit; and so on for
StartAct (SA), Block (Bl), Wait (Wt), RunSys (RS), RunUser (RU), and Halt
(Ht).
You may set T.instruction to trace any combination of privileged
instructions in this way. Here is a practical example; set T.instruction to 5
(which in binary is 00000101) thereby requesting a trace of all uses of
GetStatus and StartAct. If you set T.instruction to 0, ALL privileged instructions
are traced. The default value for T.instruction is -1.
T.sysproc
For tracing system processes. When this variable is set to a non-default value,
the simulator displays information about each execution of specified system
processes. T.sysproc uses one bit for each process, like this
---------------------------------. . . | | | |Tr|Un|Sh|Lo|Pr|Di|
---------------------------------So, to display information about the DiskScheduler (Di), set the rightmost bit; to
display information about the ProtocolHandler (Pr), set the next to rightmost bit;
and so on for Login (Lo), Shell (Sh), Unspooler (Un), and Transmitter (Tr).
You may set T.sysproc to trace any combination of system processes in this
way. Here is a practical example; set T.sysproc to 32 (which in binary is
100000) thereby requesting a trace of all uses of the Transmitter. If you set
Jeeves
24 June 2017
System Manual
T.sysproc to 0, ALL system processes are traced.
78
The default value for
T.sysproc is -1.
T.transfer
For tracing data transfers between memory and a device. The information
about the transfer is shown when the transfer is complete, just before an
interrupt is generated. When this variable is set to a non-default value, the
simulator displays information about each specified data transfer (essentially the
same information shown in jeeves.log, with one exception). T.transfer uses one
bit for each device, like this
---------------------------------. . . | | | |Pr|Sc|Ke|Co|Di|Mo|
---------------------------------So, to display information about the Mouse (Mo), set the rightmost bit; to
display information about the Disk (Di), set the next to rightmost bit; and so on
for the Comm Interface (Co), Keyboard (Ke), Screen (Sc), and Printer (Pr).
You may set T.transfer to trace any combination of data transfers in this way.
Here is a practical example, set T.transfer to 18 (which in binary is 010010) to
trace all Disk transfers and Screen transfers. As mentioned, this trace looks
like the information in jeeves.log except for the Keyboard trace; for the
Keyboard, there is a trace shown for each character entered, instead of
showing the whole command. If T.transfer is set to 0, all data transfers will be
traced. The default value for T.transfer is -1.
T.ipaddr
For tracing what happens at a specific IP address. This variable attempts to
capture exactly what the client would see during a session at some IP address.
Actually, what is captured is more detailed than what the client would see each input and output is labeled, with I or O and the clock time. The trace
output is not sent to the screen; it is written to a file named captured.ip below
is a segment of what was captured for a simulation - you can see the labeling
Jeeves
24 June 2017
System Manual
79
of the prompts, commands, and results.
O
393942:
Jeeves>
I
480988:
list .
O
481026:
RWRW-3715
RWRW-3312
RWRW-- 23225
RWRW-677
O
481034:
Jeeves>
I
557345:
users
O
557383:
999 root
1013 dcomer
1020 nhorvath
wlewis
wlewis
wlewis
wlewis
D
P
D
D
simple.one
dosomething
another
tiny.one
To perform a capture such as this, you must set T.ipaddr to the IP address of
the client you want to see. Specify the 4-part IP address in the usual form four numbers separated by periods, for example 24.43.159.95 If the special
IP address 0.0.0.0 is specified, the inputs and outputs for all IP addresses are
captured simultaneously - this may create a rather jumbled appearance in
captured.ip; however, each input and output is labeled with its associated IP
address so that you can distinguish who is doing what. Do not embed white
space in the IP address that you specify in trace.setup.
T.start
This value controls the start of tracing. You must set it to the clock time at
which you want tracing to begin. This value affects ALL tracing variables. The
idea is that tracing does not begin until R.clock >= T.start
Of course, if
T.start is set to 0, tracing begins as soon as the simulation starts. You should
use this variable to focus on a section of time during which a problem occurs.
Jeeves
24 June 2017
System Manual
80
The default value of T.start is 600000000.
T.finish
This value controls the end of tracing. You must set it to a clock time at which
you want tracing to stop. This value affects ALL tracing variables. The idea is
that tracing continues only while R.clock <= T.finish Of course, if you set
T.finish high enough, tracing will continue throughout the simulation.
You
should use this variable to focus on a section of time during which a problem
occurs. The default value of T.finish is 600000000.
T.diskdump
This value can provide the ability to dump one or more sectors of the disk.
You must set it to a clock time at which you want to do the dump - this time
must be between T.start and T.finish.
When the specified diskdump time
occurs, the simulator prompts for the disk location of a sector (not cluster) and
then displays the specified sector in the form you specify.
This prompting
occurs repeatedly, so you can examine multiple sectors. The simulator also
asks you to specify a time for the next diskdump.
The default value for
T.diskdump is -1. Here is a sample of the prompts and responses assuming
T.diskdump is 450500 - the bold elements were entered by the programmer.
The choices of sector form are the same as are available from the diskutility
program, described later.
Disk Dump at 450500:
Surface (0-5, -1 to stop): 0
Track (0-127): 1
Sector (0-31): 9
Interpretation (Hex, Boot, Map, Folder, ASCII): f
Display for disk location (0,1,9)
Filename: mycopy
Size (in bytes): 1540 Record count: 20 Access settings: RWRW-File type: D Owner: wlewis Clusters occupied:
(0,6,28)
Surface (0-5, -1 to stop): -1
Jeeves
24 June 2017
System Manual
81
Do you want to Dump Disk at a later clock time (Y/N)? n
This dump requests to examine sector (0,1,9) as a folder - one directory entry (for file
mycopy) is found in it. Note that only one sector is shown at a time.
T.memorydump
This value can provide the ability to dump one or more 512-byte blocks
of memory. You must set it to a clock time at which you want to do the
dump - this time must be between T.start and T.finish.
When the
specified memorydump time occurs, the simulator prompts for the
memory address to begin the dump and then displays the specified
block in the form you specify. This prompting occurs repeatedly, so you
can examined multiple memory blocks. The simulator also asks you to
specify a time for the next memorydump.
T.memorydump is -1.
The default value for
Here is a sample of the dialog, assuming
T.memorydump is 611055; again, the forms are the same as those
available from diskutility.
Memory Dump at 611055:
Start Address (-1 to end): 36864
Interpretation (Hex, Boot, Map, Folder, ASCII): a
Display of memory starting at address 36864
Offset 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF
0000
CDE.wlewis simple.one 028 062ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
0040
JKLMNOPQRSTUVWXYZABCDEFGHIJ.wlewis simple.one 029 060ABCDEFGHIJK
0080
LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH.wlewis simple.
00C0
one 030 074ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA
0100
BCDEFGHIJKLMNOPQRSTUV.wlewis simple.one 031 038ABCDEFGHIJKLMNOPQ
0140
RSTUVWXYZABCDEFGHIJKL.wlewis simple.one 032 020ABCDEFGHIJKLMNOPQ
0180
RST.wlewis simple.one 033 090ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI
01C0
JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL.wlewis s
Start Address (-1 to end): -1
Do you want to Dump Memory at a later clock time (Y/N)? n
This request is to examine memory locations 36864 through 37375 as ASCII
Jeeves
24 June 2017
System Manual
82
characters - undisplayable characters are shown as periods.
To do all the tracing shown in the examples, the trace.setup file should have the
following values, in order. The values need not be on separate lines.
12
5
32
18
24.43.159.95
300000
1000000
450500
611055
Simulator Detected OS Errors
The simulator is checking many of the actions of your OS to make sure it is doing
reasonable things. When your OS does something that the simulator regards as wrong, the
simulator does three things: it displays an error message on the screen; it records the same
error message in the jeeves.log file; and it sets R.oserror to an error code number. By setting
R.oserror, the simulator is trying to communicate to your OS (not just to you) that the OS has
made a mistake. You would be wise to have your OS check the R.oserror value to be sure it
is 0 (the indication of no error) after any action that is questionable. Below is a listing of the
errors that the simulator detects along with the associated error code numbers (on the left).
Each error message appears on one line. The text beneath them is an explanation of what
you might be doing that caused the error.
1.
OS has changed R.clock to xxxx it should be yyyy
Your OS changed the value in R.clock; but your OS is not allowed to ever change the
value in R.clock.
Jeeves
24 June 2017
System Manual
2.
83
OS should not be using 'throw'
The simulator uses the 'catch' and 'throw' mechanism to simulate interrupts. Your OS
contains a 'throw' which it did not catch.
3.
OS returned from OpSys; must use priv. instr.
Your OS must never simply fall through OpSys and return. It must relinquish control of
the CPU by issuing a RunSys, RunUser, Wait, or Halt.
4.
Invalid Device: xxxx
1=Status, 2=Clear, 3=StartAct:
yyyy
The value in R.device (xxxx) is not a valid device number. The detection was made
during a GetStatus (1), Clear (2) or StartAct (3) as indicated by yyyy.
5.
Device not ready; device: xxxx
status:
yyyy
Device xxxx is not in a ready state when attempting StartAct, instead the device's state
is yyyy.
6.
Can't StartAct on device: xxxx
Your OS is attempting to start IO on device number xxxx; but it is a keyboard or a
mouse.
7.
Invalid surface: xxxx
The disk has surfaces numbered 0 through 5, not xxxx.
8.
Invalid track: xxxx
The disk has tracks numbered 0 through 127, not xxxx.
9.
Invalid sector: xxxx
The disk has sectors numbered 0 through 31, not xxxx.
10.
Invalid disk action - not R or W or S
The disk can only read (R) or write (W) or seek (S); some other character was found
in the action register. The action must be in uppercase.
11.
Not on page frame start: xxxx is address, device yyyy
Disk reads and writes and printer writes must involve transfers to/from a memory
address that is the start of a page frame, i.e., a multiple of 2048. xxxx is not such a
multiple; yyyy is the device in question.
Jeeves
24 June 2017
System Manual
12.
84
Invalid data transfer size: xxxx
Disk reads and writes must involve some multiple of the number of bytes in a sector
(512). xxxx is not a multiple of 512.
13.
No system service with processid: xxxx
xxxx is not a system process id; such ids are 1 through 6
14.
Process id: xxxx cannot be used with RunSys
xxxx is the process id of some user process, not one of the system processes
15.
Bad address: xxxx for device yyyy
xxxx is not a valid memory address for a StartAct using device yyyy
16.
Bad data size: xxxx bytes for device yyyy
The number of bytes that can be transferred to device yyyy must be in the range 0 to
2048; it cannot be xxxx
17
Lost input from device xxxx due to locked status
Device xxxx was not cleared when input arrived on it. The input was discarded. Your
OS did not Clear the device after its previous input.
18.
Inappropriate device: xxxx to use Clear on
Only devices that can have spontaneous input (Mouse, Keyboard, and Comm Input)
require clearing; device xxxx does not
19.
Must issue Halt at Power_Down interrupt
When a Power_Down interrupt occurs, your OS must issue a Halt. It cannot attempt
any other actions.
20.
Return from system process xxxx must use Block
The last action of every system process must be to Block itself. System processes are
not allowed to return; but xxxx did.
21.
Invalid use of Block, process xxxx
The Block trap can be used only by system processes; however, a Block occurred
while the current process id was xxxx (not a system process id)
22.
Context not restored for thread xxxx
Jeeves
24 June 2017
System Manual
85
When a user program is executing and an interrupt occurs, your OS must save the
thread's context (pc and genpur values) so that it can be restored when the thread is
next selected for execution. Also, when a system process blocks, your OS must save
its context so that it can be restored when the system process is next executed. In
this case, your OS did not do this for thread xxxx.
23.
Bad CRC16 value, was xxxx should be yyyy for host zzzz
The crc16 field of an IP header for an output message is not correct. Your OS is
responsible for calculating the crc16 value for all outgoing messages. The message to
host zzzz contained xxxx in the crc16 field; it should have had yyyy
24.
Bad sequence number, was xxxx should be yyyy for host zzzz
The sequence number of every outgoing message should match the sequence number
of the incoming message that it is a response to. The last incoming message from
host zzzz had sequence number yyyy; the last outgoing message had sequence
number xxxx.
25.
Client skipped authentication: subnet xxxx host yyyy
The client on subnet xxxx, host yyyy tried to use the server without properly starting a
session; i.e., did not begin by sending a SYN message.
26.
Invalid printer action = not B or P or E
The printer can only receive data into its buffer (B), print the contents of the buffer
(P), or eject a page (E); some other character was found in the action register. The
action must be in uppercase.
27.
Invalid data size for printer: xxxx
The specified data size (xxxx) is too large; the printer buffer can hold only 8192 bytes.
28.
Invalid printer buffer address: xxxx
The printer buffer address (place where data is to be transferred to) must be a
multiple of 2048; instead, it was xxxx
29.
Pagemap[0] invalid for system process: xxxx
Every system process should have pagemap[0] set to valid==1, resident==1, and
Jeeves
24 June 2017
System Manual
86
pageframe==90+processid In this case, process xxxx does not have that.
30.
Invalid opcode at address
xxxx
thread
yyyy
The user program instruction found at address xxxx for thread yyyy is not one of the
recognized operations.
Almost certainly, the pagemap for yyyy is corrupted or
R.process.pgmioaddr is invalid.
31.
Invalid pagemap entry; address:
xxxx
thread
yyyy
A reference was made to address xxxx by thread yyyy; however, the pagemap is not
set up to allow such a reference.
Below is a sample of what an error message would look like when it appears on the screen.
This error message is indicating that the disk is busy at the time (567332) your OS is
attempting to issue a StartAct on it.
567332 *** Error code 5 ***
Device not ready; device: 16
status:
1
Tools
In addition to the simulator program, several program tools are available to help you
test and refine your OS. These tools let you custom design a script so that you can test
some situation without the distraction that may be created by other client or device actions that
are part of one of the official scripts. In this section, these tools are described.
scripter
scripter is a program that lets you create a script file in whatever way you want. If you
want to have a script that has one or more clients log in and do some specific command(s)
Jeeves
24 June 2017
System Manual
87
and nothing else, you can make such a script with this program. Execute the scripter program
and answer the questions it asks to make the script. The overall design of scripter is such
that you are expected to enter the messages from one client's session at once; however, the
program is flexible enough to allow you to break the session into pieces if you want to. As
you enter commands, be aware of the clock times so that you space the commands out in a
realistic way and so that you do not create a typeahead situation or a jumbled command.
You can have the session involve any IP address, even Jeeves own if you choose to have the
input come from the console. In addition, you can create special events in a script (enabling
or disabling printers or generating SYN messages that are really destined for some server
other than Jeeves).
The following discussion is about each of the prompts that scripter
displays; these are shown in the approximate order they would appear when you execute the
program.
Enter script file name:
Here respond with a file name. If the file already exists, scripter assumes you want to
append more sessions or events to it; if the file does not exist, scripter starts to create
a new script file. Suggestion: use a .scr extension for the name of script files; it
makes them easy to recognize.
Session (Telnet, FTP, Keyboard, Printer, Bogus or Quit):
Here specify what category of events you want to create by entering the first letter of
each of the key words. T to create or add to a Telnet session; F to create or add to
an FTP session, K to create commands from the keyboard (console), P to enable or
disable a printer, B to create messages that should go to some server other than
Jeeves, and Q to terminate the program. T and F are handled in much the same way;
consider what happens when you enter either of these; you see
Enter IP address as four dot-separated numbers:
Jeeves
24 June 2017
System Manual
88
Enter some IP address. It may be any valid address, except for Jeeves own address.
Do not put spaces in the address. Sample: 144.80.128.7
Message type (SYN, PSH, FIN or Quit):
You are responsible for making sure the messages constitute a valid session - begin
with one SYN, followed by one or more PSHes, and end with a PSH containing a
logout or quit command or a FIN. Enter just the first letter of whatever message
type you want (S, P, F, or Q). If you enter S, you see
Arrival time:
Enter the time (in ticks) when you want the SYN message to arrive. Remember, there
are 100,000 ticks per second. Do not choose a time before 200000 so that the OS
has time to do whatever it wants in setting up its database. After you enter the time,
you are prompted again for a message type. This time enter P and see
Arrival time:
again. This time you are being asked for the time of the first message with command
content. Choose some time after the SYN. scripter then assumes that you will want
to enter multiple PSH messages and so does not go back to asking for a message
type or arrival time. Instead, you are repeatedly prompted with
Text (command) to send:
Enter a command that is to go to the server. If this is the first command line, you
should enter a username (the server always asks the client to log in before doing any
Jeeves
24 June 2017
System Manual
89
of his/her commands). When the prompt appears a second time, enter the client's
password.
Then at subsequent prompts, enter valid Telnet or FTP commands
(depending on what type of session you specified). Usually, the last command you
enter is logout (Telnet) or quit (FTP). When prompted after the last command,
just press enter alone. For each of the entered messages, scripter is calculating arrival
times for them based on what you entered for the first arrival time. When you press
enter alone, scripter tells you how far the time reached with a display:
Last time reached:
xxxxxx
It then prompts again for a message
type. You may at that point chose P and enter more commands (it asks for a new
arrival time). If you choose FIN or Quit, scripter prompts with
Enter new IP address (0.0.0.0 to end):
You may enter commands for a second session by specifying the IP address of
another client or enter 0.0.0.0 if you don't have any more sessions to add. Any IP
address other than 0.0.0.0 leads to the message type prompt again (where you should
begin with a SYN, as before). Entering 0.0.0.0 causes the session prompt to be
displayed again.
There is one special situation for FTP sessions; it occurs when the "put" command is
used. The "put" command is used by a client to transfer a copy of a file from the
client's machine to Jeeves. After this command is entered, the next entry at the Text
prompt should specify the file to be transfered, the form is
@filespecification
filesize
This is not a prompt, you must enter this
information to tell scripter what file to use as the source for the transfer (this is a real
file in your current directory); the filesize is the number of bytes to send. scripter
takes the first filesize bytes, packages them into messages of no more than 512 bytes
and puts the messages into the script. scripter takes this special action only when the
Jeeves
24 June 2017
System Manual
90
command line begins with an @.
Whenever you see the "Session" prompt, you may choose any session type so that a
single script file can contain any combination of session types. If you choose the K
(keyboard) session type, the following prompt appears
Command (Enter only to end):
Enter a Telnet command (or user ID or password). The first time this prompt appears,
you should enter a user name to begin the authentication process. scripter responds
by displaying the prompt
Start time:
Unlike remote Telnet and FTP sessions in which scripter determines the timing of
subsequent messages, for the console, you must specify the time for each command
line. scripter does assign times to each keystroke that is part of the command. After
you specify the time, scripter displays a message such as,
Command ends at xxxxxx
before prompting for the next command. It
does this so you know how far the clock advanced by entering the previous command.
When you just press enter at the command prompt, scripter again prompts for the
session type.
If you choose P for printer, scripter displays the prompt
Disable or Enable:
Enter a D or E to specify the printer action. scripter then asks for a time
Jeeves
24 June 2017
System Manual
91
At what time:
Enter the time you want the enable or disable to occur. The session type prompt is
then redisplayed.
If you choose B for bogus at the session type prompt, scripter prompts with
Number of messages:
Enter the number of bogus messages that you want scripter to generate. These are
SYN messages (no PSH, FIN, or ACK bogus messages are generated) that are
coming from some random IP address and are destined to be delivered to another
server on the same subnet as Jeeves.
messages is not 144.201.193.179
So, the destination IP address in these
Such messages are coming to Jeeves' Comm
Interface because Jeeves is on a bus network with these other servers. scripter then
asks for a
Starting time:
Enter the time that you want the first bogus message to arrive. scripter also prompts
for the approximate time between bogus messages with
Rough separation:
Again, enter a time of separation between bogus messages. The bogus messages are
not exactly separated by this amount; scripter adjusts the true separation.
When you choose Q (Quit) at the session type prompt, scripter terminates, writing the
script file with the specifications you have given. As indicated at the beginning, you may
Jeeves
24 June 2017
System Manual
92
choose to add more sessions or events to a script file later. Unfortunately, there is no tool
available to delete or change the contents of events in a script file. So, if you make a
mistake in creating the file, you have to start over. Script files are binary and cannot be
edited easily. Below is a sample script creation using scripter. The script being made is
meant to test the FTP command "put"; the elements in bold are what was typed in. The
script has wlewis logging in, giving a put command to transfer 3500 bytes of the sampler.txt
file to Jeeves and store it there as the file jumbled.mess in the wlewis directory. wlewis then
verifies the transfer by using a dir command.
Enter script file name: put.scr
put.scr is a brand new script file.
Session (Telnet, FTP, Keyboard, Printer, Bogus or Quit): f
Enter IP as four dot-separated numbers: 12.34.56.78
Message type (SYN, PSH, FIN or Quit): s
Arrival time: 222000
Message type (SYN, PSH, FIN or Quit): p
Arrival time: 333000
Text (command) to send: wlewis
Text (command) to send: thursday
Text (command) to send: put ./jumbled.mess
Text (command) to send: @sampler.txt 3500
Text (command) to send: dir .
Text (command) to send: quit
Text (command) to send:
Last time reached: 733660
Message type (SYN, PSH, FIN or Quit): q
Enter new IP address (0.0.0.0 to end): 0.0.0.0
Session (Telnet, FTP, Keyboard, Printer, Bogus or Quit): q
There are two programs available to view the contents of a script file. Both are useful;
one shows a summary of the events in the script - each event is shown on one line; the other
shows the complete details of each event. Having these programs means that you do not
have to keep a record of what each script file contains after you make it.
Jeeves
24 June 2017
System Manual
93
displayscript
displayscript displays a summary of the events in a script file. Every event is shown
on a single line in the order that they are stored in the file. Note that every event in the file
has an associated time and that the file need not be in chronological order.
When the
simulator reads the script file, it will put the events in chronological order, regardless of the
order in which they are in the script file. When you run displayscript, it prompts only for the
script file name and then displays the information. Below is an example of what you might
see in the display of
1
1
3
200000 F
3
300000 F
3
386641 F
3
445121 F
3
523910 F
3
607856 F
3
430201 T
3
210005 T
3
320005 T
3
370289 T
3
428214 T
3
523260 T
3
601931 T
a short script file.
123. 45. 67. 89
123. 45. 67. 89
123. 45. 67. 89
123. 45. 67. 89
123. 45. 67. 89
123. 45. 67. 89
66.247. 7.135
24. 43.159.183
24. 43.159.183
24. 43.159.183
24. 43.159.183
24. 43.159.183
24. 43.159.183
1: SYN
2: wlewis
3: thursday
4: get ./tiny.one
5: dir library
6: quit
To 144.201.193.140
1: SYN
2: jwolfe
3: wednesday
4: list library
5: now
6: logout
1: SYN
The first line shows the Boot_Done interrupt. scripter always puts this event in every script at
time 1. The format of each line is this: Interrupt/Trap code (mostly 3 for Device_In), time of
interrupt, service (F for FTP, T for Telnet), IP address of the client, sequence number of the
message, and the message itself. The one exception is the bogus message in the middle; for
it, the destination IP address is also shown. The script contains two valid sessions; the first is
an FTP session; the second is a Telnet session. If the FTP session had contained a put
command, the display would show parts of each of the message fragments for the file being
transferred. Each of these sessions contains only a couple of commands. Bogus messages
are always SYN messages. Notice that the times of the sessions completely overlap.
Jeeves
24 June 2017
System Manual
94
analyzescript
This program provides a complete analysis of a script file, showing the complete
contents of all parts of all messages. The display shows the events in storage order, just as
displayscript does. Here is how the first part of the above script is displayed by analyzescript.
Code: 1
Device: 0
Time: 1
Size: 0
Code: 3
Device: 20
Time: 200000
Size: 32
IP Header:
Version: 4 HdrSize: 5 DataSize: 12 Frag No: 0 Frag Total: 0
Protocol: T To Live: 64 CRC: 5360
Source: 123. 45. 67. 89 Destination: 144.201.193.179
TCP Header:
Source Port: 20 Destination Port: 20 Sequence No: 1
Hdr Size: 12 Msg Type: S Application: FP
Code: 3
Device: 20
Time: 300000
Size: 39
IP Header:
Version: 4 HdrSize: 5 DataSize: 19 Frag No: 0 Frag Total: 0
Protocol: T To Live: 64 CRC: 59317
Source: 123. 45. 67. 89 Destination: 144.201.193.179
TCP Header:
Source Port: 20 Destination Port: 20 Sequence No: 2
Hdr Size: 12 Msg Type: P Application: FP
Message text: wlewis
Notice that this is a great deal more verbose that displayscript. Above are shown only the
first three events from the script file. Subsequent FTP and Telnet messages are similar to the
second and third messages above. You should be able to match the elements of this display
with the components of IP and TCP headers described previously.
diskutility
With this program you can create a completely new disk for Jeeves to use or modify an
existing disk. diskutility has the ability to add or delete users, add or delete files, and display
the contents of the disk in a variety of forms. When you start the program, it prompts with
Jeeves
24 June 2017
System Manual
Disk's file name:
95
You may enter the name of an existing file that contains a disk
image or you may enter a new file name. Assume you enter my.disk If diskutility can find
my.disk, it displays:
Read existing disk named my.disk
If it cannot find the file, diskutility displays the message:
Making new disk named my.disk
and creates a new disk image.
A new disk image contains a complete boot record, bit map, and root directory. The
kernel, daemons, and password files are created, as are the library, common, and users
directories (although two of these directories are empty). The users directory has the root
directory entry in it. There is one pre-defined user, root. Its entry is the only one in the
password file.
After either retrieving a disk image from a file or constructing one, diskutility prompts
with its standard command prompt Command:
You are then expected to enter one of
the six command categories that it recognizes (Dump, File, User, Write, Help or Quit). You
need enter only the first letter of the category (upper or lowercase).
Each category is
discussed below:
Dump
Here you may specify one sector of the disk and ask to have it displayed in
one of five different forms. The prompts that appear are
Surface (0-3):
Enter the surface number; surfaces 4 and 5 cannot be specified
because they do not contain permanent information - being used
for swapping and spooling.
Track (0-127):
Enter the track number.
Sector (0-31):
Enter the sector number - remember that disk references are in
terms of clusters, so disk locations that you will see in directories
will always have the sector number as a multiple of 4. Dump is
Jeeves
24 June 2017
System Manual
96
going to show you one sector, not one cluster; all sector
numbers 0 to 31 are valid.
Interpretation (Hex, Boot, Map, Folder, ASCII):
Here you choose what interpretation you want made of the
sector. You need enter only the first letter of each form. For
"Hex", you get a hexadecimal display of each byte. For "Boot",
the sector is interpreted as a Boot record, showing number of
surfaces, number of tracks/surface, number of sectors/track,
sector size, number of sectors/cluster, and the disk locations of
the start of the bit map, root directory, kernel, swapping area,
and spooling area. For "Map", the sector is interpreted as a bit
map showing the used portions of the bit map (in hexadecimal)
and a statement of where the last used cluster is. For "Folder",
you get a display of up to four directory entries in a standard
form; here is a sample directory entry
Filename: my-first-data-file
Size (in bytes): 3127 Record count: 30 Access settings: RWRW-File type: D Owner: jwolfe Clusters occupied:
(0,6,4) (0,6,8)
For "ASCII", you get a display of the sector as characters;
however, undisplayable characters are shown as periods.
File
Here you may create new files or delete files from any folder. You can also
see a listing of what files are in a folder and get a display of the contents of a
file. The prompts are as follows
Folder name: You may enter any valid folder name.
File action: Add(A), Delete(D), List(L), Show(S):
Choose "Add" to create a new file and put it in the folder. The subsequent
Jeeves
24 June 2017
System Manual
97
prompts for Add are:
File name:
Any valid file name is allowed
Who owns this file? This prompt appears only if the folder is library or common. For
these folders, any user may be the file's owner. You need to
specify a valid user name.
Data(D) or Program(P):
You may create either a data or program file. diskutility
asks for parameters of the file; but it generates the
contents. For data files, diskutility prompts with
Number of records: Enter a reasonable number. There is no specific limit because
the records vary in size; you cannot make a file that occupies
more than 48 KB.
Smallest size of data record:
This is the fewest number of characters that can
appear in a record, in addition to the folder, file
name, sequence number and record size which
are a part of every data record.
For program files, diskutility prompts with
Number of reads (400 max):
Enter how many reads you want the program to
make (if it runs successfully).
Number of writes (800 max):
Enter how many writes you want the program to
make (if it runs successfully).
Speed (1-10, 1=fastest):
Programs can be made to execute at different
speeds - 1 is the fastest; programs at speed 10
take about 10 times longer than programs at
speed 1 (to do the same number of I/O actions).
Have Program Terminate (T) or Abort (A):
Enter T to cause the program to end normally or
A to cause the program to abort.
Jeeves
24 June 2017
System Manual
98
If you choose "Delete" at the File Action prompt, diskutility prompts with
File name:
Whatever file you specify is deleted.
If you choose "List" at the File Action prompt, diskutility displays a basic listing
of the files in the folder; perhaps, something like this.
File Name
simple.one
problem
another
mixup.txt
list.h
P O W Bytes
RWRW-- 3715
RWRW-- 2280
RWRW-- 24607
RWRW-- 3672
RWRW-- 7632
Recs
50
570
302
47
7632
Type
D
P
D
D
T
Owner
wlewis
wlewis
wlewis
wlewis
wlewis
If you choose "Show" at the File Action prompt, diskutility prompts with
File name:
Whatever file you specify is displayed. diskutility examines the
file type and handles the adjustment necessary to display data
files, program files or transfer files.
Folder files cannot be
displayed with Show; also, you should not attempt to use Show
on the password, kernel, or daemons files.
User
Here you may create new users, delete existing users, or list the password
information about the users. Note, that deletion of a user implies deletion of all
files of that user; diskutility handles this automatically.
Also, this category
contains the only command that you can use which shows the decrypted
passwords of the users on the disk. The prompts for this category are
Add (A), Delete (D), List (L) Users:
Enter the letter which indicates the action you want to perform. If you choose
"Add", diskutility prompts with
New User Name:
Enter the username (8 characters maximum).
Jeeves
24 June 2017
System Manual
99
xxxxx's password (no white space):
The xxxxx is the user name you specified. The password must
be at least 6 characters long.
User ID number:
Enter a unique ID number (a value greater than 1000).
If you choose "Delete" at the User Action prompt, diskutility prompts with
User to delete:
Whatever username you enter causes that user to be removed
totally from the disk. All the user's files are deleted, the user's
entry in the users directory is removed and the user's entry in
the password file is removed.
If you choose "List" at the User action prompt, diskutility displays a table like
the following one
UID
1020
1035
1121
Write
User
nhorvath
jwolfe
wlewis
Encrypted Password
yZNrzhp4mBk95Rk9b
zQd2aDMD9ks.T8t9M
otc0QDYLGA69O9t92
Decrypted
tuesday
wednesday
thursday
This choice is used to write the changed or created disk image to a file. When
you choose this category, diskutility prompts with
New Disk file name (Enter only to write xxxxxxx):
The xxxxxxx is the name of the file you specified when you started to
execute diskutility. If you simply press enter, the xxxxxxx file is written.
If you enter some other name, that file is written. In this way, you can
create one disk image from another one and still have the original or
update the original. diskutility then displays
Disk yyyyyyy written + internal update done.
Where yyyyyyy is the name of the file actually written (whether it is the
original or a new file). Note that the message says "internal update
Jeeves
24 June 2017
System Manual
100
done". diskutility does NOT immediately update everything internally
as you do add and delete commands; only after you Write are some
updates made. diskutility does not terminate upon writing the file; you
can still give more commands.
Help
This displays a brief explanation of each of the command categories and what
they are about.
Quit
This terminates the program. Because termination is independent of writing the
disk image, you can make test changes to a disk image and then quit, without
ever writing it to a file.
File Summary
The following files are significant in conjunction with the COSC 432 project. Some of
the files are provided to you in the /usr2/fac/jlwolfe/jeeves directory. Some are created when
the simulator executes. One is to be created by you, if you want to execute in a controlled
way. Files that are in bold are binary; do not try to display or print them. Files in normal font
are text files; they may be examined or printed or edited, as you wish.
Principal Files
answer.*
A collection of files from a simulator execution, including the
script and all output files produced by the simulator. The script
has one client try all Telnet commands. The script is binary; the
other answer files are text.
analyzescript Exec. Shows the details of all events in a script file.
basics.h
Inc.
Contains struct definitions for all registers, tracers, memory, and
Jeeves
24 June 2017
System Manual
101
all message components
captured.ip
Produced by the simulator, contains a record of all activity at an
IP address (or all IP addresses) during a simulation.
diskutility
Exec. Displays or changes information in a disk file.
displayscript Exec. Shows basic information about each event of a script.
example.cc
Pgm. A sample program to show how the simulator can be used to
access information on the disk and send messages to an IP
address.
execution.log
Produced by the simulator, contains a record of the program
input and output of all user process threads.
jeeves.log
Produced by the simulator, contains a record of all transfer
activity during a simulation.
jeeves.o
Link
The object file containing the code for the simulator, the encrypt
function, and the CRC function.
jeeves.report
Produced by the simulator, contains a summary of device
actions, client actions, interrupts, privileged instructions, system
process use and disk changes.
minisave
Cmd
printer.log
Command file for renaming simple simulator produced files.
Produced by the simulator, contains all data actually printed on
the printer, with ejection markers separating files.
saveit
Cmd
Command file for renaming all simulator produced files.
scripter
Exec. Provides a way to create a script containing any combination of
client actions.
skeleton.cc
Pgm. A sample operating system that does almost nothing.
str.h
Inc.
Contains struct, union, and typedef definitions for all file system
and disk structures.
stringin.cc
Pgm. A sample program to illustrate the use of istrstream for input from
a c-string.
Jeeves
24 June 2017
System Manual
thedisk
thedisk.final
102
The file containing the disk information - read by the simulator.
A file containing the disk information after a simulation has terminated.
trace.setup
A data file read by the simulator to specify trace variable values.
*.scr
A collection of script files. A more detailed explanation of each
script file is contained in another table.
Files that are labeled "Exec." above are executable; and those labeled "Cmd" above are
command files; both of these groups should be copied to your own ./bin directory. This
directory is in your path by default so you can then execute these programs and command
files by simply typing their names at the bash prompt. Files that are labeled "Inc." should be
copied to the directory which you are using to work on this project. These files should then
be included in your OS source code, preferably near the beginning. Files that are labeled
"Pgm." are C++ programs - two of them (example.cc and skeleton.cc) are pseudo operating
systems which can be compiled and linked with jeeves.o to make a complete program.
Scripts
Below is a brief description of the script files that are provided for your testing of your
OS. Additional script files may be provided later.
hello.scr
One Telnet client login and logout only
comm1.scr
One Telnet client tries now, list, users, and show; one FTP client tries
dir and get; the clients act consecutively.
comm2.scr
One Telnet client on the console followed by an invalid login and one
FTP client; commands are similar to comm1.scr
comm3.scr
Two Telnet clients enter commands simultaneously; there are a few
illegal commands; there are messages meant for other servers
comm4.scr
Several clients log in, three on different IP addresses simultaneously;
Jeeves
24 June 2017
System Manual
103
one IP address is used consecutively by clients; there are messages
meant for other servers; there are illegal commands; three clients access
the one file at the same time; mixture of FTP and Telnet.
accesses.scr Several access commands with list commands to verify them.
copies.scr
Several copy commands with list commands to verify them.
deletes.scr
Several delete commands with list commands to verify them.
adds.scr
Several add commands with users and list commands to verify them.
removes.scr
Several remove commands with users and list commands.
done1.scr
A selection of access, copy, and delete commands.
done2.scr
A selection of root operations: add, remove, root-only access.
done3.scr
A selection of mostly put and print commands, with printer status
changes.
done4.scr
A selection of mostly run commands and tests of them.
done5.scr
Everything I can think of.
now.scr
Single now command
list.scr
Single list command
dir.scr
Single dir command
users.scr
Single users command
get.scr
Single get command
show.scr
Single show command
access.scr
Access command followed by a list to see the effect.
copy.scr
Copy command followed by a list to see the effect.
delete.scr
Delete command followed by list to see the effect.
add.scr
Add command followed by users and list to see the effect.
remove.scr
Remove followed by users and list to see the effect.
put.scr
print.scr
run.scr
Put command followed by dir to see the effect.
Single print command
Run command followed by list to see the effect.
Jeeves
24 June 2017
System Manual
104
Programs
Below are listings of several of the program files that are provided to you. They are
included here so that you will have a convenient reference to their contents.
basic.h Definitions for all registers, tracers, memory, and message components
struct pmentry
{
unsigned char
unsigned char
unsigned short
};
struct classBaddr
{
unsigned char
unsigned char
unsigned char
};
union ipn
{
long
classBaddr
};
struct pregs
{
long
long
long
classBaddr
pmentry
long
long
};
struct ioregs
{
long
long
long
long
long
unsigned char
// Page Map Entry Form
resident;
valid;
pageframe;
// Indicates if page is in memory
// Indicates if page is part of program
// Page Frame number
// Class B IP Address Form
netid[2];
subnet;
host;
// Network ID in two parts
// Subnet number (mask is 255.255.255.0)
// Host number
// Union to allow dissection of an IP addr
whole;
ipv4;
// Treat as a single value
// Treat as a class B address for Version 4
// Process Control Registers
userid;
processid;
thread;
ipaddr;
pagemap[16];
pgmioaddr;
pgmiosize;
//
//
//
//
//
//
//
User Identification number
Process ID number
Thread number - unique
IP responsible for process
Page map for process
Virtual address of program I/O
Size of program I/O data
// Input/Output Control Registers
address;
datasize;
packetin;
mousein;
keyin;
surface;
//
//
//
//
//
//
Physical address of memory involved
Number of bytes to transfer
Physical address of where to put packet
Physical address of where to put mouse info
Physical address of where to put character
Disk Surface number
Jeeves
24 June 2017
System Manual
unsigned char
unsigned char
char
long
105
track;
sector;
action;
//
//
//
//
bufferaddr; //
Disk Track number
Disk Sector number
R to read, W to write, S to seek,
B to send to buffer, P to print, E to eject
Buffer address for printer
};
struct registers
{
long
long
long
long
long
long
long
long
ioregs
pregs
};
// Registers for Jeeves
clock;
timer;
icode;
device;
state;
pc;
genpur[8];
oserror;
io;
process;
struct tracers
{
int
icode;
int
instruction;
int
sysproc;
int
transfer;
ipn
ipaddr;
int
start;
int
finish;
int
diskdump;
int
memorydump;
};
typedef char
struct tcpheader
{
short
short
long
char
char
char
//
//
//
//
//
//
//
//
//
//
Clock - ticks each 10 microseconds
Alarm clock - settable
Interrupt/Trap code number
Device number for interrupts & commands
Device status
Program counter
General purpose registers
OS Error code number
I/O register group
Process control register group
// Tracer values
//
//
//
//
//
//
//
//
//
Interrupt/Trap(s) to trace
Privileged Instruction(s) to trace
System process to trace
Data transfer category(ies) to trace
IP to trace
Clock time to start trace
Clock time to end trace
Dump part of disk indicator
Dump part of memory indicator
memory[128*1024];
// Jeeves' memory form
// Simplified TCP message header
srcport;
destport;
sequence;
hlength;
msgtype;
appl[2];
//
//
//
//
//
//
//
Source port number
Destination port number
Message sequence number, unique
Header size (in bytes) (always 12)
Message type: S (syn), P (psh),
A (ack), F (fin)
Application code: TN (telnet), FP (FTP)
};
struct ipheader
{
char
char
short
short
char
char
// Simplified IP message header
version;
hlength;
dlength;
fragment;
ftotal;
protocol;
//
//
//
//
//
//
Version number (always 4)
Header size (in 32-bit units) (always 5)
Data size - bytes in TCP header + data
Fragment number - for large messages
Total number of fragments, usually 0
Protocol (always T - for TCP)
Jeeves
24 June 2017
System Manual
106
short
unsigned short
classBaddr
classBaddr
timetolive;
crc16;
source;
dest;
//
//
//
//
Time to live (always 64)
16-bit cyclic redundancy check value
IP of message source
IP of message destination
};
struct message
{
ipheader
tcpheader
char
};
str.h
// Interface message form
ip;
tcp;
data[512];
// IP header (20 bytes)
// TCP header (12 bytes)
// Data (content) of message
Contains struct, union, and typedef definitions for
all file system and disk structures
typedef char
typedef char
fname[28];
id[9];
struct diskloc
{
unsigned char
unsigned char
unsigned char
};
// Data type for a file name
// Data type for a user name
// Disk Location
surface;
track;
sector;
struct
{
char
accesspair
char
wrtdel;
rdexe;
// Surface number (0-5)
// Track number (0-127)
// Sector number (0-31)
// Access control spec
//
//
//
//
R
E
W
C
(read, list, execute),
(execute only), - (none)
(update, append, create, delete)
(create only), - (none)
};
struct direntform
// Directory entry form
{
fname
filename;
// File name
long
filesize;
// Size in bytes
long
recordcount;
// Size in records
accesspair
access[3];
// Access control specs for
// System, Owner, and World, in order
char
kind;
// Type of file (F, D, P or T)
id
owner;
// Name of user who owns file
char
slack[4];
// First character is *
diskloc
diskref[24];
// Disk locations for clusters
};
typedef char
struct
{
char
long
long
map[6][128];
bootform
// Data type for bit map
// Boot record form
jump[12];
surfaces;
tracks;
// Fake instruction to boot
// Number of surfaces on disk
// Number of tracks / surface
Jeeves
24 June 2017
System Manual
107
long
long
long
diskloc
diskloc
diskloc
diskloc
sectors;
sectorSize;
clusterSize;
accounting;
rootdir;
theOS;
spooling[2];
diskloc
swapping[2];
char
bootstrap[1992];
//
//
//
//
//
//
//
//
//
//
//
Number of sectors / track
Number of bytes / sector
Number of sectors / cluster
Disk location of bit map
Disk location of root directory
Disk location of kernel
Starting and ending disk locations
of spooling area
Starting and ending disk location
of swapping area
Fake bootstrap program
};
struct diskuse
{
map
bitmap;
diskloc
lastcluster;
char
slack[1277];
};
// Layout of cluster with bit map
struct
{
long
id
char
};
// Data type of a password file record
// The bit map itself
// Disk location of last used cluster
// Junk - wasted space
secret
uid;
username;
encrypted[19];
struct instr
{
char
unsigned char
unsigned short
};
// User Identification Number
// User name
// Encrypted password
// User program instruction layout
opcode;
elapse;
virtaddr;
// Operation to perform
// How long the operation takes
// Virtual memory address that
// the instruction references
union clusterform
// Multiple forms a cluster can take
{
bootform
home;
// Boot record form
diskuse
themap;
// Bit map form
direntform
dentry[16];
// Directory form
secret
usafe[64];
// Password file form
instr
pgm[512];
// Program form
char
data[2048];
// Plain group of bytes
};
typedef clusterform
typedef atrack
skeleton.cc
atrack[8];
asurface[128];
// Data type for a disk track
// Data type for a disk surface
Minimal program that behaves enough like an
operating system to run the simulator, without
generating errors. Ignores all interrupts (except
for clearing them) and terminates at Power_Down
#include <iostream>
Jeeves
24 June 2017
System Manual
108
#include <string>
using namespace std;
#include <queue>
#include "basics.h"
#include "str.h"
// STL queue
// Structs, types, union for regs and comm
// Structs, unions, types for disk
extern registers
extern tracers
extern memory
R;
T;
M;
void
void
void
void
void
void
void
void
Halt();
Wait();
Block();
RunSys();
RunUser();
GetStatus();
StartIO();
Clear();
// Jeeves' Registers
// Trace variables
// Jeeves Memory
// Privileged instructions
void BootStrap();
void encrypt (char [], char []);
unsigned short CRC (ipheader &);
void
void
void
void
void
void
DiskScheduler ();
ProtocolHandler ();
Login ();
Shell ();
Unspooler ();
Transmitter ();
// To start the simulator
// To encrypt passwords
// For cyclic redundancy checks
// System processes
// Put your Global structs and variables here or use an include
int main ()
{
BootStrap();
}
void OpSys()
{
if (R.icode == 3)
Clear();
else if (R.icode == 2)
Halt();
Wait();
}
// Only statement allowed in main
// Entry to the Operating System
// Clear input interrupts
// Terminate on Power_Down
// Wait for everything to happen
void DiskScheduler (void)
{ }
// stub
void ProtocolHandler (void)
{ }
// stub
void Login (void)
{ }
// stub
Jeeves
24 June 2017
System Manual
109
void Shell (void)
{ }
void Unspooler (void)
{ }
// stub
void Transmitter (void)
{ }
// stub
example.cc
// stub
A program to extract file information from any disk. The directory structure
display that it produces is sent to IP address 12.34.56.78 Because
communication with any IP address is expected to be initiated from that IP
address; the simulator reports the following error when example is executed.
The program is still allowed to continue.
Note: This program assumes a simple directory (having fewer than 17 entries)
for every directory.
2372 *** Error Code 25 ***
Client skipped authentication: subnet 56 host 78
// This program is not an operating system. It's purpose it to extract
// directory and file information from the disk. It displays this info
// in each directory level by level, with labels. The program contains
// its own interrupt handling and message generating functions; it interacts
// with the simulator in ways similar to an operating system. The program
// sends output to IP address 12.34.56.78; trace this IP address to see it
#include <iostream>
#include <iomanip>
#include <strstream>
using namespace std;
#include <queue>
#include "basics.h"
#include "str.h"
extern registers
extern tracers
extern memory
void Halt();
// STL queue
// Structs, types, union for regs and comm
// Structs, unions, types for disk
R;
T;
M;
// Jeeves' Registers
// Trace variables
// Jeeves Memory
// Privileged instructions
Jeeves
24 June 2017
System Manual
void
void
void
void
void
void
void
110
Wait();
Block();
RunSys();
RunUser();
GetStatus();
StartAct();
Clear();
void BootStrap();
void encrypt (char [], char []);
unsigned short CRC (ipheader &);
// To start the simulator
// To encrypt passwords
// For cyclic redundancy checks
void
void
void
void
void
void
// System processes
DiskScheduler ();
ProtocolHandler ();
Login ();
Shell ();
Unspooler ();
Transmitter ();
// Global structs and variables
struct tcbform
{
pregs
long
long
};
struct diskreq
{
unsigned char
unsigned char
unsigned char
char
long
int
char
int
};
struct packet
{
int
start;
int
size;
};
// Each thread has a tcbform
regs;
pc;
genpur[8];
// Process registers for the thread
// Program counter value when stopped
// General purpose registers when stopped
// Entry for disk queue
surface;
track;
sector;
action;
addr;
category;
level[9];
count;
//
//
//
//
//
//
//
//
surface number
track number
sector number
action to take (R, W, S)
memory address
type of request
directory name
number of entries in directory
// Output packet info
// Where it begins in memory
// how many bytes it is
union combine
// Union to assemble and dissemble a message
{
message
detail;
// Standard message form
char
text[544]; // Overlay with characters
};
queue<diskreq>
queue<tcbform>
queue<packet>
diskq;
readyq;
messageq;
// Queue of disk requests
// Queue of ready threads
// Queue of outgoing packets
Jeeves
24 June 2017
System Manual
111
int
int
int
int
outBuffer = 10240;
bufferPtr = 0;
interfaceState = 0;
runningThread = 0;
//
//
//
//
const
const
const
const
int
int
int
int
// Categories for disk actions
tcbform
tcbform
BOOTREAD = 1;
ROOTREAD = 2;
DIRREAD = 3;
USERREAD = 4;
Base address for packets
Offset into packet storage
Interface state: 0 free, 1 busy
Number of thread that is running
// Templates for disk scheduler and transmitter threads
dsched = {{999, 1, 100, {144,201,193,179}, {{1,1,91},
0}, 0}, 0, {0}};
// DiskScheduler
transmit = {{999, 6, 100, {144,201,193,179}, {{1,1,96},
0}, 0}, 0, {0}};
// Transmitter
void DiskDriver (void);
void InterfaceOut (void);
void BlockThread (void);
int main ()
{
BootStrap();
}
// Responds to disk interrupts
// Responds to comm output interrupts
// Responds to block traps
// Standard main program
// All that is allowed in main
// Place a request in the disk queue
void DiskRequest (int surf, int trk, int sect, // surface, track, sector
char act,
// Action R read, W write, S seek
int place,
// Memory address to read/write
int cat,
// Category for DiskDriver action
char level[],
// Name on higher level directory
int count)
// # Entries in directory
{
diskreq
starter;
// A queue entry
starter.surface = surf;
starter.track = trk;
// Fill queue entry and enqueue it
starter.sector = sect;
starter.action = act;
starter.addr = place;
starter.category = cat;
strcpy(starter.level, level);
starter.count = count;
diskq.push(starter);
}
// Operating System entry point
void OpSys()
{
tcbform
chosen;
// Used in CPU scheduling
int
j;
// Loop index
Jeeves
24 June 2017
System Manual
112
if (runningThread > 0)
// If a thread was running,
{
// save the context elements
readyq.front().pc = R.pc;
for (j = 0; j < 8; j++)
readyq.front().genpur[j] = R.genpur[j];
}
runningThread = 0;
// Indicate no thread is running
switch (R.icode)
// Respond to interrupt or trap
{
case 1:
// Boot_Done
DiskRequest (0,0,0,'R',4096,BOOTREAD," ",0);
// Request boot record
dsched.pc = transmit.pc = R.pc = 0;
// Initialize contexts
for (j = 0; j < 8; j++)
// of DiskSched & Trans
dsched.genpur[j] = transmit.genpur[j] = R.genpur[j] = 0;
readyq.push(dsched);
break;
case 2:
// Power_Down
Halt();
break;
case 3:
// Device_In
if (R.device == 20 || R.device == 9)
// Ignore keyboard & comm in
Clear();
else if (R.device == 19)
// Respond only to disk
DiskDriver();
break;
case 4:
// Device_Out
if (R.device == 20)
// Respond only to comm out
InterfaceOut();
break;
case 8:
// Block_Self
BlockThread();
// Block the thread
break;
}
if (!readyq.empty())
// If threads ready, schedule one
{
chosen = readyq.front();
// Get first thread in queue
R.process = chosen.regs;
// Restore context
R.pc = chosen.pc;
for (j = 0; j < 8; j++)
R.genpur[j] = chosen.genpur[j];
runningThread = R.process.thread;
// Note which thread this is
RunSys();
// Start it executing
}
else
Wait();
// If nothing is ready, wait
}
// Save the contest of the thread at front of the queue
// Then, remove it from the ready queue
void BlockThread (void)
{
if (readyq.front().regs.processid == 1)
dsched = readyq.front();
// Is it the DiskScheduler?
Jeeves
24 June 2017
System Manual
113
else
transmit = readyq.front();
readyq.pop();
// Remove thread from readyq
}
// Disk scheduler system process
void DiskScheduler (void)
{
diskreq
front;
// Request at front of queue
R.device = 19;
// Set device and make sure it is ready
do {
GetStatus();
} while (R.state == 7);
front = diskq.front();
// Get request info into registers
R.io.surface = front.surface;
R.io.track = front.track;
R.io.sector = front.sector;
R.io.action = front.action;
R.io.address = front.addr;
R.io.datasize = 2048;
StartAct();
// Initiate disk operation
Block();
// Ask to be blocked
}
// The other system processes must be defined, although they are
// not needed in this program
void ProtocolHandler (void)
{ }
// stub
void Login (void)
{ }
// stub
void Shell (void)
{ }
// stub
void Unspooler (void)
{ }
// stub
// Transmit packets system process
void Transmitter (void)
{
packet
front;
// Output packet queue entry
front = messageq.front();
// Get next output packet queue entry
R.device = 20;
// Make sure comm out is ready
do {
GetStatus();
} while (R.state == 7);
R.io.address = front.start;
// Set up registers
Jeeves
24 June 2017
System Manual
114
R.io.datasize = front.size;
StartAct();
interfaceState = 1;
Block();
// Initiate output
// Mark Comm Interface busy
// Block transmitter
}
// Build a packet for output
// Most elements of the message are fixed by the nature of the program
// and are initialized when tosend is declared
void MakeMessage (char text[])
// text is packet content
{
message
tosend = { {4, 5, 0, 0, 0,'T', 64, 0, {144,201,193,179},
{12,34,56,78}}, {23, 23, 1, 12, 'A', 'T', 'N'}, 0};
// This initializes the message as follows: IP header // version=4, hlength=5, dlength=fragment=ftotal=0, protocol=T
// timetolive=64, crc16=0, source=144.201.193.179,
// dest=12.34.56.78, TCP header - srcport=destport=23, sequence=1,
// hlength=12, msgtype=A, appl=TN
int
combine
packet
j;
lump;
msgref;
// Loop index
// Union for assembly of message
// Outgoing packet for queue
strcpy(tosend.data, text);
tosend.ip.dlength = 13 + strlen(text);
tosend.ip.crc16 = CRC (tosend.ip);
lump.detail = tosend;
for (j = 0; j < tosend.ip.dlength+20; j++)
M[outBuffer+bufferPtr+j] = lump.text[j];
msgref.start = outBuffer + bufferPtr;
msgref.size = tosend.ip.dlength + 20;
bufferPtr += msgref.size;
messageq.push(msgref);
if (interfaceState == 0)
readyq.push(transmit);
// Put data in message
// Compute length
// Calculate CRC
// Put msg in memory
// Fill out msg queue entry
// Adjust for next message
// Enqueue the request
// If Comm Interface is ready
// awaken Transmitter
}
// Collect directory entry information into a message
void FormLines (char text[],
// Message being formed
clusterform & chunk,
// Just read cluster
int count,
// Number of directory entries
char lead[])
// Padding to indent
{
char
holding[500] = { 0 };
ostrstream
internal(holding,500,ios::app);
// Internal stream
int
j;
for (j = 0; j < count; j++)
// Append info from each dir ent
{
internal << lead << chunk.dentry[j].kind << setw(6)
<< chunk.dentry[j].recordcount << " "
<< chunk.dentry[j].filename << endl;
Jeeves
24 June 2017
System Manual
}
internal << ends;
strcat (text, holding);
115
// Attach a null
// Add to message header
}
// Respond to disk interrupts
void DiskDriver (void)
{
int
j;
diskreq
front;
clusterform
chunk;
int
limit;
int
rootrecords;
diskloc
position;
char
text[512];
diskloc
rootloc;
front = diskq.front();
diskq.pop();
//
//
//
//
//
//
//
//
Loop index
Copy of disk request
Used for dissecting clusters
Loop control for processing dir ents
Number of entries in root directory
First disk reference for each entry
Area in which to form a message
Disk reference for root directory
// Get queue front
// Discard queue entry
switch (front.category)
// Processing based on reason for request
{
case BOOTREAD:
// Read of Boot record
for (j = 0; j < 2048; j++)
chunk.data[j] = M[front.addr+j];
rootloc = chunk.home.rootdir;
// Get root dir location
// Request read of root directory
DiskRequest (rootloc.surface, rootloc.track, rootloc.sector,
'R',4096,ROOTREAD," ",0);
break;
case ROOTREAD:
// Read of root directory
for (j = 0; j < 2048; j++)
chunk.data[j] = M[front.addr+j];
rootrecords = chunk.dentry[0].recordcount;
// Get # root entries
// from 1st cluster
strcpy (text, "Entries in root\n");
// Start first msg
for (j = 1; j < rootrecords; j++)
{
if (chunk.dentry[j].kind == 'F')
// If entry is a folder
{
// read its 1st cluster
position = chunk.dentry[j].diskref[0];
DiskRequest (position.surface, position.track, position.sector,
'R',4096, DIRREAD, chunk.dentry[j].filename,
chunk.dentry[j].recordcount);
}
}
FormLines (text, chunk, rootrecords, " ");
// Add dir ents
MakeMessage (text);
// Put message in queue
break;
case DIRREAD:
for (j = 0; j < 2048; j++)
chunk.data[j] = M[front.addr+j];
// Read in a directory
Jeeves
24 June 2017
System Manual
116
strcpy
strcat
strcat
for (j
{
(text, " Entries in top-level directory ");
// Start msg
(text, front.level);
(text, "\n");
= 0; j < front.count; j++)
// If entry is a folder and the folder has some files,
// request a read of first cluster
if (chunk.dentry[j].kind == 'F' && chunk.dentry[j].recordcount > 0)
{
position = chunk.dentry[j].diskref[0]; // 1st cluster only
DiskRequest (position.surface, position.track, position.sector,
'R',4096, USERREAD, chunk.dentry[j].filename,
chunk.dentry[j].recordcount);
}
}
FormLines (text, chunk, front.count, "
MakeMessage (text);
break;
");
// Add dir ents
// Put message in queue
case USERREAD:
for (j = 0; j < 2048; j++)
// Read a user directory
chunk.data[j] = M[front.addr+j];
strcpy (text, "
Directory entries for ");
// Start msg
strcat (text, front.level);
strcat (text, "\n");
FormLines (text, chunk, front.count,"
");
// Add dir ents
MakeMessage (text);
// Put message in queue
break;
};
if (!diskq.empty())
// If diskq is not empty, make
readyq.push(dsched);
// scheduler ready
}
// Respond to Communication Output interrupts
void InterfaceOut (void)
{
interfaceState = 0;
messageq.pop();
if (!messageq.empty())
readyq.push(transmit);
else
bufferPtr = 0;
}
// Make Comm output ready
// Remove message from queue
// If message queue not empty,
// awaken Transmitter
// Otherwise, reset pointer
Using Linux
To make use of kodiak somewhat easier, here are a few tips on ways to organize,
compile, link, and test your files. There are also some ideas for ways to write your program
Jeeves
24 June 2017
System Manual
117
and a mini-introduction to bash, in case you have not used Linux.
Compiling, Linking, and Executing
If you do not already have a bin subdirectory, you should create one. You can do this
with a command such as
mkdir
bin
entered at your top-level directory. By
default, ~/bin is in your execution path. Therefore, when you enter a program name at the
prompt and a file of that name is in ~/bin, it will execute. The ~ is shorthand for your home
directory (for me that is /usr2/fac/jlwolfe ). You can find your home directory by giving the
pwd command immediately after logging in.
You may make a subdirectory for your source files and other files or just leave them in
the top level directory. I put my files in a subdirectory called 432. Every time I log in and
want to use this directory, I make it my default directory by entering
cd 432
Then, I can proceed to compile, link. etc. as described below
To compile a file such as example.cc, I should use the g++ (GNU C++) compiler and
give a command like
g++ -c -g example.cc
This creates an object file named example.o in the default directory. The -g argument is to
get the compiler to put vital debugging information into the object file. The -c argument
specifies that I want to compile-only, i.e., not link. If I had left the -c out, g++ would have
linked also, producing a file named a.out as an executable file in my default directory. Unless
told otherwise, g++ always names the executable a.out.
To create a more reasonable
executable file name and put the executable in an appropriate place, I would use an argument
to tell g++ what I want.
Jeeves
24 June 2017
System Manual
118
g++ -g -o ~/bin/example
example.cc
This compiles example.cc (with debugging information and tries to link the object file produced
by the compiler and build an executable file named example in the bin subdirectory. The
designation of the executable is what follows the -o argument. The ~/bin/example is the
path to where I want the executable file built. /example says make the executable file named
example. Incidentally, this command does NOT work - example.o must be combined with
jeeves.o (the simulator) to create a complete executable. So, giving the command as I am
showing it above leads to many linker errors. If I had compiled-only as first illustrated above
and then given the command
g++ -o ~/bin/example
example.o jeeves.o
this would have worked. g++ would have looked the two files as object files in the default
directory and combined them to form the executable in ~/bin.
A more convenient way to compile and link is to take advantage of the make program.
This program reads a "make file" specification of everything that goes into compiling and
linking and takes care of all the details of determining what files need to be recompiled and
linked. The make file contains two types of lines: dependencies which begin at the left
margin and specify which files are needed to create a particular "final" file and commands
which are indented and specify a compiler or linker action to perform if necessary to make the
"final" file up-to-date. Below is a make file that can be used with example.cc to create a
proper executable result.
/usr2/fac/jlwolfe/bin/example: example.o jeeves.o
g++ -o /usr2/fac/jlwolfe/bin/example example.o jeeves.o
example.o: example.cc str.h basics.h
g++ -c -g example.cc
Jeeves
24 June 2017
System Manual
119
The first line says /usr2/fac/jlwolfe/bin/example is dependent on example.o and jeeves.o
and that the command to perform if /usr2/fac/jlwolfe/bin/example is older than either of the
object files is to link the two files (as specified on the second line). Note here that full path
specifications are best in this situation; ~ seems to cause the GNU compiler a problem when
used in a make file specification. The third line says example.o is dependent on example.cc,
str.h, and basics.h and that the command to perform if example.o is older than any of these
other files is to compile example.cc. The other files are included in example.cc If these lines
are put in a file called example.mak, then the make program can perform all of the actions
described above by processing the dependencies (bottom to top) and produce the finished
executable. To use make, give the command
make -f example.mak
For more information about make, look at the man pages or use info.
Programming Tips
To avoid having any symbol conflicts, especially when debugging, I recommend that
you do not name anything by using an underscore as the last character of the name. All
global type names, class names, variable names and function names that the simulator uses
end with an underscore character. (Obviously, there are exceptions for those definitions that
your operating system and the simulator share: registers, memory, encrypt, etc.) If you avoid
using underscores in this way in your operating system, there can never be a conflict over a
name.
The use of strstream is highly recommended for dealing with internal formatting needs
in your program. To interpret client commands, it is convenient to be able to "read" them in
Jeeves
24 June 2017
System Manual
120
the way cin would; however, commands arrive in a message packet as a whole string; and
your OS must be able to dissect them - strstream can help. To construct outgoing message
packets, the data portion needs to be formed in the same way one might use cout to "write";
however, the data portion must be combined with the headers and the whole thing must be
sent out as a packet; your OS must build this data portion. strstream allows you to treat
strings as a streams so that istream objects like cin can "read from a c-string" and ostream
objects like cout can "write to a c-string."
There is an example of how to use strstream for output in example.cc (in the
FormLines function). The idea is simple. Declare a large character string area and initialize it
to null. Then, declare an ostrstream object that can be used to output to the c-string area
(the arguments in the declaration are: the char array, the size, and the mode - I used mode
app to have each output element appended as the c-string was formed). Then, output using
the ostrstream object just as you would any ostream object (including manipulators if you
want). The output of ends at the end of the c-string ensures that it ends with null. The
result can then be treated like any null-terminated c-string in C++.
In FormLines, I
concatenated this string with the header to form the complete message. Note: the c-string
and ostrstream object are deliberately declared inside the function so that they are created
new when the function is entered and destroyed when the function exits.
There is no input using strstream in example.cc; but the idea is similar, with one little
quirk. The object being declared is an istrstream; however, it takes one or two arguments.
Here are two examples
istrstream
first (stash);
stash must be a pre-existing null-terminated string. That
is, at the point this declaration appears, stash must
already have in it the complete contents that will serve as
Jeeves
24 June 2017
System Manual
121
an input stream for first
istrstream
second (slow, 50); Here slow must be previously declared and capable of
holding 50 characters; however, later actions may put the
characters in slow, as long as they are in slow before
second is used to extract them from the stream
istrstream is very useful for parsing. It can be used to extract the components of a command
which is held in a c-string.
There is a sample program (named stringin.cc) that uses
istrstream to parse a Telnet copy command; it is in the /usr2/fac/jlwolfe/jeeves directory.
Notes: C-Strings used for istrstream cannot be reused after reading; there is no way to start
over at the beginning and read the string again, unless a new istrstream object is created. CStrings used for ostrstream cannot be reused after writing; there is no way to rewrite such cstrings, unless a new ostrstream object is created.
Take advantage of the way the STL implements linked lists and queues. Even though
pointers are used, there is little chance that the methods for these functions will cause the
dreaded "Segmentation Fault" error, if you take the precaution of checking before accessing a
structure or using an iterator. I would recommend that when any problem is detected, you
program should display an error message and use the "exit" function. This means that if you
execute your OS under gdb control with a break point set on exit, when the function is
reached, you can enter the backtrace command and locate the error almost immediately. If
you do get a segmentation fault, it is always caused by using an array index that is outside
the proper range for the array - unless you use some of your own pointers or use some more
dangerous implementation of linked lists and queues. When a segmentation fault occurs, it is
followed by a core dump - an image of the program at the time of the crash is written to a
file, usually named core. This file can be analyzed after the crash by using gdb. You need
Jeeves
24 June 2017
System Manual
122
to be aware that the core file will occupy 12.5 to 13 megabytes of disk space; so you
probably won't want to keep it around for long.
Two auxiliary functions are part of the simulator and are provided for your use. They
are encrypt to encrypt passwords and CRC to calculate the 16-bit Cyclic Redundancy Check
code. Use of both of the functions is quite easy. encrypt is a void function that takes two
arguments; both are null terminated c-strings: the first argument is the clear-text password
entered by a client, the second is the encrypted password that the function produces. CRC
returns an unsigned short result (the CRC16 value) and takes one argument, a reference to
an IP header in which the CRC16 field has been set to zero. There is a use of CRC in the
MakeMessage function in example.cc.
A Few bash Commands
For those of you that have not used Linux or bash (the command language shell),
here is a brief description of a few commands that you probably need for the course. In
addition to the parameters shown for the commands, many of these commands have
arguments that qualify the actions of the command. To see these arguments, use man on the
command name.
cd [directory]
Changes the default directory (the directory whose files you can refer to
without qualification).
The directory specified may be specified
absolutely as a path such as /usr2/student/course/spring2003 or
specified relatively as in bin or ./bin or ../bin or it may be omitted to
make the users home directory the default.
cp sfile dfile
Copies the source file (sfile) to the destination file (dfile).
Jeeves
24 June 2017
System Manual
ls [directory][file]
123
List the files in a directory or that match the file specification. If no
directory is specified, the default is assumed. If no file is specified, all
files are assumed. The file specification may contain wildcard characters
and multiple specifications can be given in the same command,
separated by spaces. A common argument to use with this command is
-l to get the long (more detailed) listing.
mkdir spec
Creates a subdirectory in the default directory and names it spec
mv sfile dfile
Renames the sfile to be dfile
pwd
Displays what the default directory is at the moment.
rm file
Deletes (removes) the specified file. Multiple files may be specified,
separated by spaces.
rmdir directory
Deletes the specified directory and all the files in it.
chmod code file
Sets the access protection of the specified file to the designated code.
The code is a 3-digit octal number in which each digit represents a
category level and each bit of a digit indicates an access capability.
The bit positions are 4: read, 2: write, 1: execute. The categories are
owner, group, world.
The default protection is 755 (owner has all
access, group and world have read and execute).
umask code
When placed in the .bash_profile file, causes all subsequently created
files to have their access protection modified by the code. It is highly
Jeeves
24 June 2017
System Manual
124
recommended that you put the command umask 066 in this file because
the default access protection gives everyone read access to your files.
The umask command will at least eliminate that.
cat file
Displays the contents of file on the screen.
more file
Displays the contents of file on the screen, one screen-full at a time.
Character command input is required to move through the file. Space
moves forward one screen; 'b' moves back one screen; 'q' quits.
who
Displays a listing of what users are currently logged in.
ps
Displays system process information.
quota
Displays how much disk space you have used with your files and how
much you are allowed.
man program Displays the "man" (manual) pages for the specified program.
passwd
logout
Used to change your password.
Terminate the session.
Collecting the Stuff to Hand In
For the Communications Phase and the Implementation Phase, you are required to
hand in printouts and files. kodiak does not have a printer and there are a lot of files to hand
in. What can you do?
Jeeves
24 June 2017
System Manual
125
First, the printouts of your operating system must meet three requirements:
1.
There must be no wrapping of lines. By now, you should have developed the habit of
writing reasonable length lines in programs. Lines which wrap around the end are both
confusing and ugly.
2.
There must be no compiler or linker errors in your programs. I would suggest that you
get into the habit of maintaining various versions of your program. emacs helps you
with this; whenever you do a save of file xxxx with emacs, it renames the old version
xxxx~ before writing the new xxxx file. But you probably need more than this. Build
your operating system incrementally. When you get it working up to a point, save that
source somewhere and then start adding more features to a copy. This will give you a
program that at least compiles and links to fall back on in case you don't get the
newer version working by the deadline.
3.
The font should not use proportionate spacing and there should be no word processing
features used.
I recommend printing the file with NotePad or something equally
simple. Do not try to put the file in a word processor that lets you manipulate the font
or font style or pagination.
Although kodiak has no printer, you can still print on any local or network printer that is
attached to your computer. There is a script on kodiak called pcprint that is designed to be
used in the form
pcprint
file
When
executed
through
Kermit,
this
command causes file to be printed on whatever printer is associated with LPT1.
Unfortunately, the printouts produced by pcprint are in 12-point type and have no page
numbers; nevertheless, these printouts could satisfy the three requirements.
Jeeves
24 June 2017
System Manual
126
An alternative to pcprint is to use FTP to transfer your files from kodiak to your PC,
then load each file into NotePad and print it. This has the advantage of allowing you to select
10-point if you want and to put the file name and page numbers on each page. Make sure
you transfer the file in ASCII mode.
WARNING: Although it is fine to transfer files from kodiak to the PC for printing, it is
not such a good idea to try transfers in the other direction.
emacs performs automatic
indenting as you write a program; this makes alignment of statements within a loop or decision
easy. Wordprocessors, even NotePad, on a PC do not format the source code in the same
way. Consequently, if you try to write part of your program on a PC and then transfer it to
kodiak for compilation, linking, debugging, many of the lines will be shifted when emacs or gdb
is used - and you will almost have to use emacs to make a few small changes, unless you
want to go totally crazy using FTP.
FTP is also the answer for getting files like captured.ip, jeeves.log, etc. onto a disk for
you to hand in. The problem is that the assignments ask you to provide multiple files for each
of several scripts; and the scripts always produce files of the same name. Here is how to
overcome this problem.
Copy the files saveit and minisave from /usr2/fac/jlwolfe/jeeves to your bin directory
and change their access to allow execution (chmod 700 saveit). Each of these files is a
script that is meant to be run after executing the simulator. The saveit script renames all the
files that the simulator outputs to so that you can run the simulator again without wiping out
the results of the first execution.
Suppose you just executed the simulator using script
comm1.scr; then, run the saveit script by entering:
saveit comm1
This causes jeeves.log to be renamed comm1.log and jeeves.report to be renamed
comm1.report and so on. minisave is almost the same as saveit, except it does not rename
Jeeves
24 June 2017
System Manual
127
the printer.log and execution.log files - it makes more sense to use minisave with comm1
because the comm1.scr script does not produce any printing or execution output. Below is a
listing of saveit.
# Rename the key files after simulator execution
# Check if argument (prefix) is missing
if [ -z "$1" ]; then
echo "No prefix specified"
echo "Usage: saveit prefix"
else
# Rename all simulator output files using the prefix
if [ -f captured.ip ]; then
mv captured.ip $1.capture
fi
mv jeeves.log $1.log
mv jeeves.report $1.report
mv printer.log $1.print
mv execution.log $1.exec
fi
Comment lines start with # The first if tests the command line argument, $1, to be sure it is
present. The second if tests to make sure captured.ip exists. This is a simple script but it
still contains more complicated features of bash than you should need in the course.
Once the output files have been named and the required scripts executed, you can use
FTP to transfer the renamed files to a disk and hand it in.
C++ Elements
It is assumed that you know how to use lists and queues (and other data structures).
Jeeves
24 June 2017
System Manual
128
To avoid having you create your own classes to make these objects, you may use the
Standard Template Library template classes (in fact, you are encouraged to use them). You
can see examples of using the queue template in the example.cc program. To use STL
queues, put the line #include <queue> in your program and declare the queues you want,
similar to those in example.cc. The principal member functions for STL queues are
int size ( )
Returns the number of entries in the queue
void pop ( )
Deletes the front entry of a queue
void push (DataType &)
Adds an entry of DataType to the rear of the queue
DataType & front ( )
Returns a reference to the front entry of the queue
bool empty ( )
Returns an indication as to whether the queue is empty
To use STL lists, put the line #include <list> in your program and declare the lists you want.
The list class comes with an embedded iterator class that you may use to access the list
entries. The principal member functions for STL lists are
int size ( )
Returns the number of entries in the list
iterator begin ( )
Returns an iterator to the first entry in the list
iterator end ( )
Returns an iterator to a place beyond the last entry of the list
iterator insert (iterator & past, DataType &)
Inserts a node just before the node pointed to by iterator past and puts
in it the data specified. The return value refers to the new node.
void erase (iterator)
Deletes the node referred to by the iterator
bool empty ( )
Returns an indication as to whether the list is empty
The principal member functions for the STL list iterators are
operator++ ( )
Advances the iterator to the next node
Jeeves
24 June 2017
System Manual
129
operator-- ( )
Backs up the iterator to the previous node
operator== ( )
To compare iterators for equality
operator!= ( )
operator* ( )
To compare iterators for inequality
To "dereference" the iterator, get a reference to the data
element of a node
operator-> ( )
To get a pointer to the data element of a node
If you do not want to use the STL template classes, an alternate is provided in the file
listque.h This file contains a queue template class, named Queue_, a list template class,
named Linked_List_, and a separate list iterator class, named List_Itr_. The use of these
classes is not the same as the STL templates; however, they do work; and you may use them
if you wish.
It is possible that you have not had much experience using c-strings (arrays of char
that are null terminated). If you include <string.h> in your program, you will have access to
many functions for manipulating c-strings. These are not member functions for a class; they
are stand-alone functions that may be applied to any array of char. Below are a brief list of
the principal functions; in each of them, the char * arguments are c-strings.
int strlen (char *)
Returns the length of the c-string (not counting null)
char * strcpy (char *d, char * s)
Copies the c-string s to the c-string d; returns a pointer to d
char * strncpy (char *d, char * s, int n)
Copies up to n characters of s to become the c-string at d; returns a pointer to d
char * strcat (char *d, char *s)
Concatenates the c-string s to the c-string d; returns a pointer to the new d
char * strncat (char *d, char *s, int n)
Jeeves
24 June 2017
System Manual
130
Concatenates up to n characters of s to d; returns a pointer to the new d
int strcmp (char *d, char *s)
Returns an integer indication of how d compares to s; if d < s, return is < 0; if d ==
s, return is 0; if d > s, return is > 0
int strncmp (char *d, char *s, int n)
Returns an integer indication of how the first n characters of d compare to s; return
value is the same as for strcmp
char * strchr (char *s, char missing)
Returns a pointer to the first occurrence of character missing in c-string s
char * strrchr (char *s, char m)
Returns a pointer to the last occurrence of character missing in c-string s
char * strstr (char *d, char *s)
Returns a pointer to the beginning of the first occurrence of c-string s in c-string d
If you want to examine what other functions are available, look at /usr/include/string.h
Editing With GNU Emacs
Emacs is a very comprehensive editing program. Because it has been around so long
and because it is an open source program, Emacs has grown to include all sorts of features,
many of which can only be taken advantage of in specialty environments. This page is meant
to describe how to deal with the basics of Emacs. Only enough commands are described to
make it possible to edit simple programs and text. To get a notion of how extensive Emacs
really is, try the the help command or use info.
Emacs is an editor in which all actions (functions) are either command driven (entered
at the minibuffer at the bottom of the screen) or keystroke driven (many, many keystroke
combinations have been defined to invoke commands). Most of the discussion here is about
Jeeves
24 June 2017
System Manual
131
the keystrokes. To understand them, three keys are important: Ctrl, Alt, and Esc. The Ctrl
key is used in combination with some other key or keys; Emacs documentation always refers
to the control key as C- (Capital C followed by a dash). So, Emacs would refer to Ctrl-h
(typing h while holding the Ctrl key) as C-h. Emacs also uses the Meta key in combination
with some other key or keys. The term Meta is derived from keyboards that (I don't think)
exist any more. The idea is similar to the Ctrl key; to refer to the situation of holding down
the Meta key while typing x, Emacs would show this as M-x. Although there is no Meta key,
there are two keys on the keyboard that can be used in its place (Alt and Esc); however, they
are used in different ways. To enter M-x, you can hold down Alt while typing x (because Alt
is a key that is meant to be used simultaneously with other keys); or you can type Esc
followed by x (a two-key sequence). These two methods may be used interchangeably.
A few terms may also be helpful in understanding the following terminology. Buffer- a
portion of memory that holds the contents of a file or what will become the contents of a file.
Emacs can work with many buffers at the same time; generally the buffer name is the file
name. The minibuffer is a special buffer that holds commands which are typed in. Region a portion of a buffer, from where a mark is set to where the cursor is at the moment.
Regions are used for cutting and pasting and many other tasks. Register - a portion of
memory (like the clipboard) that can hold a copy of a region. You may define many registers
and have them hold copies of any text that you want. Window - a rectangular section of the
screen. Generally, each window shows a portion of a buffer; typically, the screen shows two
windows at a time, one holding a part of a buffer being worked on and one (at the very
bottom of the screen) set aside for the minibuffer.
Starting Emacs
Enter either emacs or emacs file-specification
When emacs starts, it looks for the file .emacs in your top-level directory. If it finds this file,
Jeeves
24 June 2017
System Manual
132
emacs executes the commands that it contains. This give you a way of initializing emacs by
defining any special features that you may want. Emacs is an extensible editor; you can
define new key combinations, macros, new commands, etc. You should already have a basic
.emacs file; later there is a brief discussion of adding to this file.
Among the commands that you might want to use just after starting emacs (maybe for
the first time) is C-h This command enters the Help system where you can find out a lot of
information about emacs. Help provides a tutorial to illustrate how to use some of the basic
keystroke actions. To run the tutorial, enter t after the C-h
Help can also show you what
function (command) a key runs (C-h c) or it can describe a function (C-h f), among other
things.
Another command that is useful just after starting emacs is the one to recover from a
disconnection. Since you are using emacs through Kermit, there is a definite possibility that
you will be disconnected. Emacs maintains a keystroke log of everything you do so it is
possible to recover a file across a disconnection very easily. The most you could lose are the
last few keystrokes that you entered. To make such a recovery, log in to kodiak after you
have reestablished the connection and enter emacs (with on file specified). Then, enter M-x
You can see M-x appear in the minibuffer and the cursor is moved to that buffer. Type the
command recover-session and follow the directions on the screen to select from the saved
logs the one you want to use for recovery. Then, answer the questions 'y' or 'yes' to actually
do the recovery.
Files
If you do not specify a file when entering emacs, you can specify one later. There are
a variety of actions that can be done with files.
Here are a few; each is done with a
combination of keystrokes. For example, the first is Ctrl-x followed by Ctrl-f
Jeeves
24 June 2017
System Manual
133
Read a file into an emacs buffer
C-x C-f
Save the contents of a buffer back to the file on disk
C-x C-s
Insert the contents of another file into this buffer at the cursor
C-x i
Write the buffer to a specified file, may be different from the original file
C-x C-w
When a disk file is to be updated, the old version of the file is renamed by attaching ~ to the
end of the name; then the new version is written. Thus, at any moment, you have access to
the current version and the version before that.
Cursor Motion
Kermit provides some capability for moving the cursor. The arrow keys are mapped to
move the cursor up, down, left, or right one character position. Page Up and Page Down also
move the cursor (one screen up and one screen down, respectively).
These keys are
mapped to be emacs commands. Kermit also provides some mouse emulation - you should
be able to move the cursor to any point on the screen by pointing and double left clicking
with the mouse.
Note:
this is not very reliable because of the interaction of Kermit's
calculation of cursor positions and the use of characters like Tab in the text. But, it should
"sort of work." Emacs has many keys mapped to provide other cursor movement; here are
some of them.
Amount to move the cursor
Backward (left or up)
Forward (right or down)
One Word
M-b
M-f
One End of a Line
C-a
C-e
Jeeves
24 June 2017
System Manual
134
One Screen Full
M-v
C-v
One Page
C-x [
C-x ]
Whole Buffer
M-<
M->
Matches and Tabs
Emacs is a mode dependent editor. That is, it adapts to the programming language
being used; it does this based on the file type (.c for C programs, .cc for C++, .p for Pascal,
.f for FORTRAN). There is a mode defined for each of these languages. In applying the
mode, emacs tries to keep a program cleanly formatted, by providing automatic indentation,
matching of symbol pairs (like parentheses), and placement of comments. Whenever you
type the right member of a pair of something (parentheses, brackets, etc.), emacs shows you
which left member it matches to. It also shows you mismatches; but you must correct the
mismatches; it will not fix things for you.
Normally, entering the Tab key is a way of getting a line properly positioned based on the
indenting scheme that is built into the mode. However, there are times when you want to
indent further than emacs would on its own. To get a true Tab into your file, you enter M-i
Marking
Marking is used to define a region, a section of the buffer contents. Once marked, a
region may have a variety of operations performed on it. To mark a region, move the cursor
to where the region is to begin and enter either C-@ or C-SPC where SPC is the space key.
When you do this, the minibuffer shows a small message that says "Mark Set". Then, move
the cursor to the end of the region. Wherever the cursor is when you give a region command
determines what is in the region. Here are a few region commands that are widely used.
Jeeves
24 June 2017
System Manual
135
Note: one command uses both Ctrl and Alt (C-M-\).
Kill (delete) a region - these are saved so you can undo them
C-w
Yank (retrieve) the last thing killed - this may be a region or some
other element
C-y
Indent the region - this is mode dependent
C-M-\
Copy the region to a register
C-x x
Insert a register contents at the cursor
C-x g
Change everything in the region to uppercase
C-x u
Change everything in the region to lowercase
C-x l
When using the Copy or Insert commands, emacs prompts in the minibuffer with Copy
to register: or Insert Register: You are expected to enter the name of the register at this
point. Use names like, a or b or c, something short and easy to remember.
Above, we noted that you can delete a region with C-w. You can also delete smaller
elements of a buffer; obviously, the Backspace key and the Delete key can be used to delete
the character to the left of the cursor. Use C-d to delete the character to the right of the
cursor. In addition, you can delete a word (M-DEL for word to the left and M-d for word to
the right); here M-DEL is Alt with Delete. And you can delete all or a portion of a line (from
where the cursor is to the left end with M-O C-k or from the cursor to the right end with C-k).
The newline character is deleted only if there is nothing but white space on the line. So, a
simple way to get rid of a whole line is C-a C-k C-k to move the cursor to the left end, delete
all characters on the line, and delete the newline that remains.
Jeeves
24 June 2017
System Manual
136
Searching
Emacs provides an unusual feature for searching; it is an incremental search. These
are the kind of searches that you typically see in a windows help file when you search the
index. As you specify what to look for, each character you enter leads you to the occurrence
of the string you have entered so far. Emacs provides searching forward or backward through
a buffer. To search forward, enter C-s Emacs displays the prompt I-search: and you should
start typing the characters of what you want to search for. As you type, the contents of the
window change as emacs moves forward through the buffer finding the sequence of characters
you enter. When you get to the place you were searching for, enter any arrow key or the
ESC (escape key) to terminate the search. You can also abort the search with C-g at any
time. If the string you are searching for occurs multiple times and you want to find a later
occurrence, when you get to an early occurrence, enter C-s and emacs will move forward to
the next occurrence. Do this as often as necessary.
To search backwards (in reverse), enter C-r instead of C-s. C-r works the same way
as C-s In fact, if you are searching in one direction and get a message that says the search
failed, you may want to immediately enter the other command key to change direction for the
search. Emacs maintains the characters of the string you have entered even across changing
directions. Generally, the incremental search is case insensitive. You can force it into case
sensitivity by using uppercase or a combination of the two cases when specifying what to
search for.
Replacing Strings
To search for a string and replace it with some other string, use the command key
Jeeves
24 June 2017
System Manual
137
M-% Doing this enters a query replacement in which you are prompted first with Query
replace: at which you are expected to enter the string that is to be replaced. When you
press Enter, you are then prompted with Query replace xxx with: where xxx is what you
specified. You then need to enter the replacement string. Then, emacs searches forward for
each occurrence of the first string specified and waits for you to indicate whether the
replacement should be done. The minibuffer shows the message Query replace xxx with yyy:
(? for help) To apply the replacement, enter SPC (the space bar). Emacs will make the
replacement and go on to the next occurrence of the string. To skip an occurrence (not do
the replacement), enter DEL (the Delete key); to apply the replacement to all remaining
occurrences of the string, enter ! (exclamation point) To abandon the replacement, enter ESC
(the Escape key).
Both replacing strings and searching for strings can use regular expressions in the
string being searched for. This would make it possible to search for "wild card" strings and
strings containing special characters like newline or backslash.
This technique is not
discussed here.
Ending Emacs
The only way to end emacs is to enter the command keys C-x C-c If you have buffers
that have been changed and not saved when you enter this key combination, emacs asks you
whether or not you want to save each of the changed buffers. You have to answer for each
changed buffer separately.
There is a simple way to suspend emacs which is very handy for writing programs.
When you enter C-z emacs stops but does not terminate. The shell prompt appears and you
can enter other bash commands. So, the common way to write a program with emacs is to
Jeeves
24 June 2017
System Manual
138
edit the file, save it with C-x C-s, then enter C-z to suspend the editor and execute the
compiler. Most compilers display any error messages on the screen and tell you about the
line on which the error occurred (showing its line number). Armed with that information, you
can resume emacs (use the bash command fg), move to the line with the error and correct it.
Then, go through the whole cycle again. The next section shows you a quick way to get to
the line with the error.
Customizing Emacs
You can add your own personal touches to how emacs operates by defining additional
key combinations for your own use. In anticipation of this, emacs has provided a whole
collection of key combinations that you can define. These all begin with C-c (Ctrl-c). One of
the most common customizations is to define C-c g to be the goto-line command. When
used, this command prompts you for a line number and jumps to that line in the buffer. To
define this key combination, edit the .emacs file and put this command in it
(global-set-key "\C-cg" 'goto-line)
Be very careful when you type this.
Then, the next time you execute emacs, you will have the goto-line capability. This will make
locating compiler errors very easy.
Miscellaneous
Finally, a few miscellaneous notes. These are commands that you may find useful at
some point, depending on how far you go with emacs. The first one to switch buffers is used
frequently when making programs from multiple files; i.e., where you have a single .cc file with
many .h files included in it.
Switch between buffers (commonly used when editing two files at once)
C-x b
Delete all other windows but the one with the cursor in it (used to get
C-x 1
Jeeves
24 June 2017
System Manual
139
back to normal after using Help or looking at a list of buffers)
Undo the last change (you can use this repeatedly to undo long
sequences of actions)
C-x u
Switch the cursor to another window (used when editing multiply buffers)
C-x o
GDB, the GNU Debugger
(Most of this is taken directly from the man page for gdb and the gdb help command)
The purpose of a debugger such as GDB is to allow you to see what is going on
"inside'' another program while it executes or what another program was doing at the moment
it crashed. GDB can do four main kinds of things (plus other things in support of these) to
help you catch bugs in the act:

Start your program, specifying anything that might affect its behavior.

Make your program stop on specified conditions. These stopping places are
referred to as break points.

Examine what has happened, when your program has stopped.

Change things in your program, so you can experiment with correcting the
effects of one bug and go on to learn about another.
To make full use of gdb, you must be sure to compile with the -g option for the g++
compiler. If you fail to put in this option, you will not be able to access the symbols properly
during debugging; and you will not be able to see the source lines surrounding the places you
halt execution.
Jeeves
24 June 2017
System Manual
140
You can run gdb with no arguments or options; but the usual way to start gdb is with
one argument or two, specifying an executable program as the argument:
gdb program
You can also start with both an executable program and a core file specified:
gdb program core
When gdb executes, it uses (gdb) as a prompt, although you can change this. To get gdb to
perform an action, you ust enter a command. All commands may be abbreviated, as long as
the abbreviation is unique.
Commands Related to Execution
continue
Usage: continue [COUNT]
Continue executing the program being debugged, after a breakpoint.
A number
COUNT may be used as an argument, which means to set the ignore count of that
breakpoint to COUNT - 1 (so that the breakpoint won't break until the COUNTth time it
is reached).
kill
Kill execution of program being debugged
next
Usage: next [N]
Step program one line, proceeding through function calls. Like the "step" command as
long as function calls do not happen; when they do, the call is treated as one
instruction. Argument N means do this N times (or until the program stops for another
reason).
quit
Exit from gdb - requires confirmation if a program is executing
Jeeves
24 June 2017
System Manual
run
141
Start the program being debugged; usually used with no argument. You may specify
arguments that include "*", or "[...]"; they are expanded using "sh". Input and
output redirection with ">", "<", or ">>" are also allowed. With no arguments, uses
arguments last specified (with "run" or "set args").
step
Usage: step [N]
Step program until it reaches a different source line. Argument N means do this N
times (or until the program stops for another reason). Steps into function calls.
Commands Related to Making the Program Stop
break
Usage: break [LINE/ADDRESS/FUNCTION]
Set breakpoint at specified line or function.
Argument may be line number, function
name, or "*" and an address. If line number is specified, break at start of code for
that line. If function is specified, break at start of code for that function. If an address
is specified, break at that exact address. With no argument, uses current execution
address of selected stack frame. This is useful for breaking on return to a stack
frame. Multiple breakpoints at one place are permitted, and useful if conditional.
clear
Usage: clear [LINE/ADDRESS/FUNCTION]
Clear breakpoint at specified line or function. Argument may be line number, function
name, or "*" and an address. If line number is specified, all breakpoints in that line
are cleared. If function is specified, breakpoints at beginning of function are cleared.
If an address is specified, breakpoints at that address are cleared. With no argument,
clears all breakpoints in the line that the selected frame is executing in.
commands
Usage: commands [BREAKPOINT]
Set commands to be executed when a breakpoint is hit. Give breakpoint number as
argument after "commands". With no argument, the targeted breakpoint is the last
Jeeves
24 June 2017
System Manual
142
one set. The commands themselves follow starting on the next line. Type a line
containing "end" to indicate the end of them. Give "silent" as the first line to make
the breakpoint silent; then no output is printed when it is hit, except what the
commands print.
condition
Usage: condition BREAKPOINT COND
Specify breakpoint number to break at only if COND is true. BREAKPOINT is an
integer breakpoint number and COND is an expression to be evaluated whenever that
breakpoint is reached.
delete
Usage: delete [BREAKPOINT . . .]
Delete some breakpoints or auto-display expressions.
Arguments are breakpoint
numbers with spaces in between. To delete all breakpoints, give no argument. Also a
prefix command for deletion of other gdb objects; example:
delete display [EXPRESSION . . .]
Cancel some expressions to be displayed when program stops. Arguments are
the code numbers of the expressions to stop displaying; the expressions would
have been previously specified with the display command. No argument means
cancel all automatic-display expressions.
disable
Usage: disable [BREAKPOINT . . .]
Disable some breakpoints. Arguments are breakpoint numbers with spaces in between.
To disable all breakpoints, give no argument. A disabled breakpoint is not forgotten,
but has no effect until reenabled.
enable
Usage: enable [BREAKPOINT . . .]
Enable some breakpoints.
arguments.
Give breakpoint numbers (separated by spaces) as
With no argument, all breakpoints are enabled until you command
Jeeves
24 June 2017
System Manual
143
otherwise. This is used to cancel the effect of the "disable" command.
ignore
Usage: ignore BREAKPOINT COUNT
Set ignore-count of breakpoint number specified by BREAKPOINT to COUNT, causing
the breakpoint to be ignored COUNT - 1 times.
watch
Usage: watch EXPRESSION
Set a watchpoint for an expression. A watchpoint stops execution of your program
whenever the value of the expression changes.
until
Usage: until LINE/ADDRESS/FUNCTION
Execute until the program reaches a source line greater than the current or a specified
line or address or function (same args as break command). Execution will also stop
upon exit from the current stack frame.
xbreak
Usage: xbreak [ADDRESS/FUNCTION]
Set breakpoint at procedure exit. Argument may be function name, or "*" and an
address. If function is specified, break at end of code for that function. If an address
is specified, break at the end of the function that contains that exact address. With no
arg, uses current execution address of selected stack frame.
This is useful for
breaking on return to a stack frame.
Commands to Examine What Has Happened
backtrace or bt
Usage: bt [COUNT]
Print backtrace of all stack frames, or innermost COUNT frames. With a negative
argument, print outermost -COUNT frames. Use of the 'full' qualifier also prints the
values of the local variables.
Jeeves
24 June 2017
System Manual
144
The stack is made up of stack frames. Gdb assigns numbers to stack frames counting
from zero for the innermost (currently executing) frame. At any time gdb identifies one
frame as the "selected" frame.
Variable look-ups are done with respect to the
selected frame. When the program being debugged stops, gdb selects the innermost
frame.
The commands below can be used to select other frames by number or
address.
display
Usage: display [/FMT] EXP
Print value of expression EXP each time the program stops. FMT may be used before
EXP as in the "print" command. The format letter may be "i" or "s"; a size letter is
allowed, as in the "x" command.
EXP is used to get the address to examine; and
examining is done as in the "x" command.
With no EXP, display all currently
requested auto-display expressions.
info
Generic command for showing things about the program being debugged. Below is a
listing of some of the more useful things that can be shown.
info args
Argument variables of current stack frame
info breakpoints
Status of user-settable breakpoints
info display
Expressions to display when program stops
info frame NUM
All about stack frame NUM
info functions All function names
info line
Core addresses of the code for a source line
info locals
Local variables of current stack frame
info program Execution status of the program
info scope
List the variables local to a scope
Jeeves
24 June 2017
System Manual
list
145
Usage: list [ARGUMENT]
List specified function or line. With no argument, displays ten more lines after or
around previous listing. "list -" displays the ten lines before a previous ten-line listing.
One argument specifies a line, and ten lines are listed around that line.
Two
arguments with comma between specify starting and ending lines to list. Arguments
can be specified in these ways:
LINENUM
to list around that line in current file,
FILE:LINENUM
to list around that line in that file,
FUNCTION
to list around beginning of that function,
FILE:FUNCTION
to distinguish among like-named static functions.
*ADDRESS
to list around the line containing that address.
With two args if one is empty, it stands for ten lines away from the other arg.
print
Usage: print [/FMT] EXP
Print value of expression EXP.
Variables accessible are those of the lexical
environment of the selected stack frame, plus all those whose scope is global or an
entire file. EXP may be preceded with /FMT, where FMT is a format letter but no
count or size letter (see "x" command).
@ is a binary operator for treating
consecutive data objects anywhere in memory as an array. FOO@NUM gives an
array whose first element is FOO, whose second element is stored in the space
following where FOO is stored, etc. for a total of NUM elements. FOO must be an
expression whose value resides in memory.
ptype
Usage: ptype TYPE
Print definition of type TYPE
set
Usage: set VAR = EXP
Jeeves
24 June 2017
System Manual
146
Evaluate expression EXP and assign result to variable VAR. VAR may be a debugger
"convenience" variable (names starting with $) or an actual variable in the program
being debugged. EXP is any valid expression. Use "set variable" for variables with
names identical to set sub commands.
set also uses sub commands to modify parts of the gdb environment. A few selected
set sub commands are shown below.
set input-radix NUM Set default input radix for entering numbers to NUM
set listsize NUM
Set number of source lines gdb will list by default to NUM
set output-radix NUM
Set default output radix for printing of values to NUM
set print pretty
Make structs be displayed in an easy to read form
set radix NUM
Set default input and output number radices to NUM.
Without an argument, sets both radices back to the
default value of 10.
set variable VAR = EXP
whatis
Evaluate EXP and assign result to variable VAR
Usage: whatis EXP
Print data type of expression EXP.
x
Usage: x [/FMT] ADDRESS
Examine memory. ADDRESS is an expression for the memory address to examine.
FMT is a repeat count followed by a format letter and a size letter. Format letters are
o(octal), x(hex), d(decimal), u(unsigned decimal),
t(binary), f(float), a(address),
i(instruction), c(char) and s(string). Size letters are b(byte), h(halfword), w(word),
g(giant, 8 bytes). The specified number of objects of the specified size are printed
according to the format. Defaults for format and size letters are those previously used.
Jeeves
24 June 2017
System Manual
147
Default repeat count is 1. Default address is following last thing printed with this
command or "print".
Jeeves
24 June 2017
System Manual
148
Communications Phase
Write the user communications portion of an operating system for the Jeeves computer.
It must perform as follows:
1.
Respond to the Boot_Done interrupt by initializing your operating system's database.
This includes reading from the disk information regarding the root and user directories
and the password file.
2.
Respond to clients who send SYN messages to start a Telnet or FTP session.
Validate login attempts by the clients and send appropriate prompts to the client.
3.
Allow validly logged in Telnet clients to issue any of the following commands AND
send the appropriate output back to the clients in response to these commands:
now
4.
list
users
show
Allow validly logged in FTP clients to issue any of the following commands AND send
the appropriate output back to the clients in response to these commands:
dir
5.
get
All other valid Telnet and FTP commands (access, copy, print, put, etc.) must be
recognized as valid but no other actions are required for them yet. Respond to illegal
commands by sending an appropriate error message.
6.
Allow Telnet clients to use the logout command or to sent a FIN packet and FTP
clients to use the quit command or to send a FIN packet.
Respond with an
appropriate message for logout and quit and end the session in any case.
7.
Ignore packets that are intended for other servers.
8.
Allow a Telnet client to log in at the console keyboard. Respond to all keyboard and
screen interrupts using a device independent approach internally. Send command
responses for the console to the screen.
9.
Properly handle all Device_In and Device_Out interrupts associated with the console or
communications interface.
Jeeves
24 June 2017
System Manual
149
10.
Implement CPU scheduling for the five system processes used during this phase.
11.
Make the DiskScheduler, ProtocolHandler, Login, Shell, and Transmitter work as
described in the Jeeves System Manual.
12.
Do NOT implement a mouse driver; no script uses the mouse.
To accomplish these tasks, your operating system database should have data structures
to hold a variety of information, as examples: A linked list or array of information about each
client or thread. Information about the status of each system device. Queues for the orderly
processing of packets, disk requests, and scheduling of threads. Possibly other linked lists to
keep track of threads that are not executable.
Disk bitmap information in some form.
Directory information for each directory in some form. Buffer areas set aside in memory to
hold vital information.
Some of Jeeves' memory must be permanently allocated to hold message packets and
keystrokes. When a message arrives or a keystroke occurs, the hardware refers to registers
to know where to put the incoming data - these registers must be set and the places the
registers refer to must be ready to receive the input.
Your OS must also meet the
requirements of implementation that messages (both incoming and outgoing) must be stored in
Jeeves' memory.
It is acceptable to copy a message into an auxiliary storage area for
assembly or disassembly; but messages must remain in Jeeve's memory when in queues for
processing.
A schedule is provided so that you can gauge the pace at which you should work to
get the operating system completed. The bold dates are the deadlines for the graded parts.
To meet these, especially the design phase deadline, you will have to at least begin working
on one phase before you complete the previous phase. Don't let this panic you. Starting the
design before finishing communications will actually have a beneficial effect.
Jeeves
24 June 2017
System Manual
150
Activity
Due on
Set up the database
January 30
Submit
Printout of jeeves.log for the script hello.scr
Implement now, dir, and February 13
Printout of jeeves.log for scripts comm1.scr and
list
comm2.scr
Complete the Communi- February 25
Readable printout of all of the operating system
cations phase
you have written (no wrapped lines).
A disk
with your OS source, jeeves.log, jeeves.report,
and captured.ip (for IP addr 0.0.0.0) from
running on scripts comm1-4.scr
Complete
the
Design March 25
phase
Pseudo code, diagrams, UML or flow charts of
the design
Implement access, copy
April 3
Printout of jeeves.log and captured.ip (for IP
addr
0.0.0.0)
from
running
on
scripts
accesses.scr and copies.scr
Implement delete, add, April 17
Printout of jeeves.log and captured.ip (for IP
remove
addr 0.0.0.0) from running on deletes.scr,
adds.scr, and removes.scr
Complete
mentation
the
Imple- April 28
phase,
including print, put, and
try run
Jeeves
24 June 2017
System Manual
151
Comm Phase Evaluation
Names _______________________
Sample Only
Boot_Done Initialization
_____ (3)
users Command
_____ (4)
Setting up the database
Boot Record
_____ (2)
Session Termination
Bit Map
_____ (2)
logout
_____ (1)
Passwords
_____ (2)
quit
_____ (1)
Root Directory
_____ (2)
FIN message
_____ (1)
Login attempts
SYN
Error Handling
_____ (2)
Authentication _____ (4)
Prompts
_____ (2)
now Command
Message form _____ (2)
Elements
_____ (4)
Parsing
Telnet
_____ (3)
FTP
_____ (2)
Illegal commands
_____ (3)
Other valid
_____ (3)
list & dir Commands
commands
_____ (2)
Messages for Other
Message Form
_____ (3)
Elements
_____ (3)
Servers
_____ (2)
Prompts before
show & get Commands
Commands
Disassembly
_____ (4)
Fragments
_____ (3)
Memory
_____ (2)
Jeeves
24 June 2017
System Manual
152
In-Message Buffers _____ (2)
Out-Message
Buffers _____ (2)
Disk Access
_____ (2)
Keyboard
_____ (2)
Screen
_____ (2)
Device Independence
_____ (4)
System Process Structure
DiskScheduler _____ (2)
ProtocolHandler
_____ (2)
Login
_____ (2)
Shell
_____ (2)
Transmitter
_____ (2)
Documentation
Miscellaneous
_____ (10)
_____ (4)
Total __________ (100)
Jeeves
24 June 2017
System Manual
153
Design Phase
Design the remainder of an operating system for the Jeeves server that meets all of
the following requirements. Other requirements are explicitly stated or implied by the Jeeves
System Manual.
1.
All Telnet and FTP commands must be recognized and acted upon correctly. Entered
commands which use an improper verb or file name must be handled by displaying
one of the specified messages. There will be NO errors due to causes other than
those shown in the manual.
2.
Output to the printer must be spooled and unspooled. Unspooling must accommodate
Device_Disables and Device_Enables on the printer. Changes in printer status must
be supported without choking the system or leaving tasks unfinished. If more print
requests are made than can be handled immediately, the operating system must
maintain a queue of them.
3.
Multiprogramming must be supported. If more than one client wishes to run a program
at the same time, the operating system must support the programs being ready to
execute simultaneously and must do so fairly.
The choice of a CPU scheduling
algorithm is up to you.
4.
Disk space management must be implemented. All used and unused space must be
kept track of at all times. The disk bitmap, the root directory and all other directories,
and the password file must be kept reasonably "current" on the disk, not just in the
database.
Jeeves
24 June 2017
System Manual
5.
154
Jeeves' memory must be managed to provide for running programs and buffers of all
kinds.
6.
root must be treated differently from all other clients. The OS must provide for getting
around some access checking for the root. The OS must also make sure that only
root can use the add and remove commands.
Your design should begin with OpSys and should include a description of what each
module is going to do (and generally how it is going to do it). You may wish to use a
flowchart or pseudo-code to illustrate the design (this is encouraged). You may wish to show
the form of tables or other data structures in the database that will be used by the operating
system (this too is encouraged). You should also provide a written explanation of the crucial
overall design decisions that you are making, for example: how memory is going to be
managed (allocated and recovered) - maybe show a picture, how printing gets started and
continues (after a lull in printing), how the disk request queue is handled, how CPU
scheduling is going to be done, how interrupts can be handled while maintaining device activity
and thread execution, how file and directory access checking and updating are to be handled,
how file conflict is detected and dealt with.
Your design should assume that you have a working communications phase. Thus,
whenever there is a need to send an error message to a client, your design may simply show
a function call and assume it will be handled (even though sending a message is an event
with an associated disconnection). Thus, in command terms, your design need only address
issues related to the client commands: access, add, copy, delete, remove, print, put, and run.
Note that each of these requires at least two things:
use of at least one page frame in
memory and at least one transfer between memory and a disk.
The complete design is due on March 25. It is highly recommended that your design
Jeeves
24 June 2017
System Manual
155
be typed (not handwritten). Naturally, if part of your design is in flowchart form or consists of
tables of values, these sections of the design need not be typed. Any handwritten parts must
be legible and intelligible.
As you know, this is a partnership project. This means that there must be cooperation
and communication between the partners. I expect to see approximately equal contributions
from each partner in each phase of the project. Of course, there may be variations during
one phase of the project or another. However, I expect to see a genuine effort at working
together. I expect that any complaints that one partner has about another partner will be
brought to me as early as possible, before a problem develops that makes working together
impossible.
WARNING: DESIGNS ARE VERY IMPORTANT. Bad designs very often lead
to bad implementations. Past experience shows that only 5% of bad designs
lead to successful programs; 20% of bad designs lead to marginal programs;
75% of bad designs lead to truly horrible programs.
Jeeves
24 June 2017
System Manual
156
Design Evaluation
Names _____________________
Sample Only
Commands
access (4)
_____
File Access Checking (3)
_____
add (4)
_____
Memory management (4)
_____
remove (4)
_____
Printing
Disk usage (1)
copy (6)
_____
_____
Spooling (4)
delete (6)
_____
put (6)
_____
print/run (4)
_____
Queue (2)
_____
Unspooling (6)
_____
_____
Library/Common (2)
_____
Device Enable/Disable (3)
Error messages (3)
File Conflict Checking (3)
User Process Thread Support
Input (3)
_____
Output (3)
_____
Time Out (2)
_____
_____
_____
_____
Jeeves
24 June 2017
System Manual
Termination (3)
157
_____
Context Switching (2)
_____
CPU Scheduling (2)
_____
Differentiating Disk Actions (6)
_____
Connections (4)
_____
Readability (10)
_____
Total (100)
_____
Jeeves
24 June 2017
System Manual
158
Implementing an Operating System
(Due on or before 28 April)
Based on the design that your partnership submitted (and suggestions that I have
made or will make), write a C++ operating system for the Jeeves server.
I suggest that you approach this task gradually by implementing some basic structures
to support the simpler commands and work your way up to handling the most complicated
commands (the Communications Phase description suggests a sequence to work on the
commands). Probably, you will want to handle print, put and run last. A variety of scripts are
available for you to test your operating system.
Each of these scripts is kept in the
/usr2/fac/jlwolfe/jeeves directory. The Jeeves System Manual briefly describes each of the
scripts that are provided.
Hand in a well-documented listing of your operating system. It is NOT acceptable to
hand in a program that has compilation or linking errors. It is NOT acceptable to hand in a
program printout in which the lines wrap. Your program MUST execute, whether it does the
right thing or not. You must also hand in a disk with the source program and the jeeves.log,
jeeves.report, captured.ip, printer.log, and execution.log files produced by executing on scripts
done1.scr through done5.scr.
If you construct any scripts of your own to demonstrate some feature of your operating
system and want to show me that something works for your script (even if it doesn't work for
mine), you may hand in these same files for those scripts. Be sure to name the files so I can
differentiate them from the required ones.
Notes:
Jeeves
24 June 2017
System Manual
1.
Look at the grading scheme.
159
You should see that the implementation of the run
command (the hardest one to implement) has relatively few points associated with it.
This is because I want you to concentrate on getting everything less to work first; then,
try run if you have the time.
2.
Hopefully, at this stage, your Communications Phase worked well enough and your
Design was complete enough for you to begin implementing as soon as you hand in
the Design. Do not wait for my evaluation of your design to start to work on the
implementation.
Jeeves
24 June 2017
System Manual
160
Implementation Evaluation
Names _____________________
Sample Only
Command Implementation
(Breakdown: 8 - complete, 6 - marginal, 3 - some code, 0 - nothing)
copy (8)
_____
access (8)
add (8)
_____
put (8)
remove (8)
_____
delete (8)
_____
_____
_____
print (6)
run (4)
_____
_____
Total _____
(58)
Task Implementation (numbers shown are maximum possible)
Interrupt handling
Disk I/O handling
Enable/Disable
_____ (6)
_____ (2)
User Thread Trap Handling
Input/Output
Time Out
_____ (6)
_____ (2)
Jeeves
24 June 2017
System Manual
Terminate/Abort
Space management (memory, disk)
161
_____ (2)
_____ (5)
Printing
Queueing
_____ (2)
Unspooling
_____ (5)
Error reporting & messages
Documentation
_____ (2)
_____ (10)
Total _____ (42)
OVERALL
__________