The operating system should execute as many programs as possible. In particular, if one program fails due to some error condition, the operating system should throw it out and continue to tend to the other running programs (if any). Under no circumstances should a failing program cause the operating system itself to fail.
The index block - disk block 0, the first block on the disk - contains an index of the programs in the disk. The ith word of the index block contains the size in disk blocks of the ith program in the batch disk. Unused entries in the index block are set to zero. Every batch disk contains an index block.
For example, this diagram
shows a batch disk containing three programs. The first program has size 3;
that is, the first program occupies three disk blocks. The second program has
size 1 and the third program has size 2.
A program is loaded in User Space in order of increasing addresses. The
contents of the program's first disk block is loaded into User Space starting at
location i; the contents of the program's second disk block is loaded into
User Space starting at location i + disk_block_size
; and so on. The
program's blocks must all fit in User Space. A program may be loaded anywere in
User Space it can fit.
Once loaded into primary storage, the program's first instruction has address i, the address of the first word of the program. The program counter should be set to i when the program first executes.
After boot-up initialization, the operating system should load and begin executing the first program on the batch disk; word 0 of the index block contains information on the first program. If the batch disk contains no programs, the operating system should halt.
exec
, exit
,
yield
, put_slot
and get_slot
. These are the first of many
system calls you will be implementing in these assignments, so you might want
to give some though to designing an easily changeable system-call
implementation (or you have to be willing to throw-away and rewrite your
system-call implementation several times, which is probably the better approach
to take).
The system calls can be split into two groups: process-management system calls and inter-process communication system calls.
system_call::exit
)system_call::exec
)status::ok | command completed successfully |
status::bad_id | there is no process with the given id |
status::no_resource | required resource not available |
and register 1 contains the new process's id if the exec was successful; otherwise the contents of register 1 is undefined.
The contents of registers 0 and 2 through 10 in the new process (the child process) are identical to the contents of the associated registers in the process that issued the exec (the parent process). Register 1 in the child process contains the parent process's id.
system_call::yield
)status::ok
.
system_call::put_slot
)status::ok | command completed successfully |
status::bad_id | there is no process with the given id |
status::no_resource | required resource not available |
If register 0 contains status::ok
when the put-slot call returns, then the
given value was succsfully written into the receiving process's slot (note that
this does not imply that the receiving process has read the value from its
slot). If register 0 contains status::no_resource
, then the attempt to write
the given value into receiver's slot has failed because the slot already
contains an unread value.
system_call::get_slot
)status::ok | command completed successfully |
status::no_resource | required resource not available |
If register 0 contains status::ok
when the get-slot call returns, then register
1 contains the value read from the slot and register 2 contains the id of the
process that put the value. If register 0 contains status::no_resource
, then
the slot didn't contain a value, and the contents of registers 1 and 2 are
undefined.
/export/home/classes/cs-438-505/pa1
contains some batch disks you can
use to test your operating system:
pa1-empty.dsk
- The empty disk; it contains no programs.
pa1-solo.dsk
- A single program does nothing for a while and then calls
exit.
pa1-bad.dsk
- A disk containing a program that does bad things.
Despite all the bad things that are going on, there should be no output other
than the usual end of execution information.
pa1-execs.dsk
- A disk containing two programs. The first program sets
a count and execs the second program. Each second program reduces the count by
one and, if the count is still positive, execs another copy of the second
program.
pa1-dcs.dsk
- The first, client, process execs the second, server,
process and sends it a value. The doubling server receives a value, doubles it
and sends it back to the client. Then both processes exit.
pa1-ydcs.dsk
- Like dcs but the client yields if the get-slot system
call fails.
pa1-tree.dsk
- A root process execs two child processes, each of which
execs two child processes and so on until they all form a seven-process
complete binary tree, then the leaves pass values back to their parents and
exit, and so on.
pa1-ytree.dsk
- Same as pa1-tree.dsk
except processes yield
whenever a put- or get-slot system call fails.
My solution to the first programming assignment, sys-os1
where
sys is either solaris
or linux
, is available in /export/home/classes/cs-438-505/pa1
. In
addition to the debug-flag values accepted by the
simulator, os1
also implements the following:
f31
- print process activity to std-err.
f30
- print successful put- and get-slot activity to std-err.
You should not be concerned about matching your operating system's timing to
the timings from os1
; timing varies depending on implementation details.
However, the SYSC
system-call instruction counts - obtained with the
ins_cnts
flag - from your operating system should
match exactly the instruction counts from os1
.
If you're looking for a way to proceed, you might want to consider the following steps:
This page last modified on 13 November 2004.