Part A of the first project will be to explore the process abstraction in the UNIX/MINIX system interface. The following programs must be implemented in C:
1. A C program that
IMPORTANT: sketch a diagram of process interaction that reasonably "captures" the behavior of this concurrent program.
2. A C program that provides the "scaffolding" for linking (piping) together n "filter" processes to form a simple pipelined bubble sort of <= n values. n must be an input parameter of your program. A filter is straightforward - it is a C program that reads from standard input and writes to standard output.
The following are input/output specifications for the overall bubble sorter:
INPUT:
A sequence of lines from standard input. Each line is a sequence of integers separated by one or more blanks. Each integer is a sequence of digits.
OUTPUT: Output is a sequence of lines where:
The C scaffolding program must
HINT: most (if not all) of the middle sorting filters can be "instantiated" from 1 basic filter "template".
IMPORTANT: Again, sketch a diagram that captures the behavior of this concurrent program. Is it more or less "complicated" than program 1?
Part B - Files:
3. There is a way to pass parameters to a C program when that program is executed directly from the Shell command line. Figure out how to do it, and explain the technique in your HW. It is described in a number of popular texts on C programming in Unix, including chapter five of the classic Kernighan and Ritchie C text The C Programming Language (I have a copy in my office). Use this technique in each of the following programs.
4. Write a C program to create a new link to a previously created file. Enter the simple filename for both the source and target files as command line parameters. Use the link system call.
5. Write a C program CopyAlias to determine whether or not two filenames refer to two distinct files but have the same contents.
The Virtual Machine
The virtual machine viewed by a user program is illustrated in figure 1. It first appeared as an assignment in The Logical Design of Operating Systems, by Alan C. Shaw, Prentice-Hall, 1974. Storage consists of a maximum of 100 words, addressed from 00 to 99; each word is divided into four one-byte units, where a byte may contain any character acceptable by the host machine. The CPU has three registers of interest: a four-byte general register R, a one-byte "Boolean" toggle C, which may contain either `T' (true) or `F' (false), and a two-byte instruction counter IC.
figure 1
A storage word may be interpreted as an instruction or data word. The operation code of an instruction occupies the two high-order bytes of the word, and the operand address appears in the two low-order bytes. figure 2 gives the format and interpretation of each instruction. Note that the input instruction (GD) reads 10 data items into 10 successive storage locations, and that the output instruction prints 10 storage locations at a time. The first instruction of a program must always appear in location 00, which the virtual machine will assume is the first program instruction.
Instruction Set of Virtual Machine
The following is the instruction set for your BRAIN02 virtual machine. You may not, under any circumstances, add additional instructions to the set.
| Operator | Operand | Interpretation |
|---|---|---|
| LR | x1x2 | R := [a]; |
| LL | x1x2 | R := zz[a]3[a]4; |
| LH | x1x2 | R := [a]1[a]2zz |
| SR | x1x2 | [a] := R; |
| CE | x1x2 | if R = [a] then C := 'T' else C := 'F'; |
| CL | x1x2 | if R < [a] then C := 'T' else C := 'F'; |
| BT | x1x2 | if C = 'T' then IC := a; |
| BU | x1x2 | IC := a; |
| GD | x1x2 | Read( [b+i], i = 0,...,9); |
| PD | x1x2 | Print( [b+i], i = 0,...,9); |
| AD | x1x2 | R := R + [a]; |
| SU | x1x2 | R := R - [a], R >= [a]; |
| MU | x1x2 | R := R * [a]; |
| DI | x1x2 | R := R / [a], [a] > 0; |
| NP | x1x2 | null operation (no-op); |
| H | halt; |
Enter instructions one per line, starting in the first character of the line, with no blanks between the operator and operand. After at least one blank, a non-interpretable comment may complete the line.
Form of a BRAIN02 Program file:
You are required to write this program in C/C++ BUT you may write the program on any platform (gcc/g++ on Unix, Borland C++ or Visual C++, Metroworks Codewarrior, etc.). A diagram of the virtual and physical virtual machines appears in figure 3 below:
figure 3
Input Data Format:
Since you may pre-load up to 10 BRAIN02 programs, the input "data" (BRAIN02 programs and data that THEY will read) should be in the following format:
BRAIN02 (start of first BRAIN02 program) info for storage location 0 info for storage location 1 . . . info for storage location < 99 BRAIN02 (start of second BRAIN02 program) info for storage location 0 info for storage location 1 . . . info for storage location < 99 BRAIN02 (start of third BRAIN02 program) . . . BRAIN02 (start of nth BRAIN02 program, where n <= 10) info for storage location 0 info for storage location 1 . . . info for storage location < 99 DATA data lines in same format as in project 2 ENDImportant: The process id of each BRAIN02 program is assigned in the order in which the program is read in above, starting from 0 (so n BRAIN02 programs will be numbered 0 through n-1).
Message Passing Instructions for BRAIN02 Process Communication:
Add the following additional message passing instructions to your BRAIN02 virtual machine.
1. Add the two communication operations:
SD x1x2where SD sends a message to the BRAIN02 process with process id x1x2, and RC receives a message from the BRAIN02 process with process id x1x2. The special command RCXX is a "receive from any process" command.RC x1x2
For a send message SD, the source of the message should be in the ten memory locations including and following the memory address in the register R, and for a receive message RC, the target of the message is defined similarly.
These operations should be blocking sends and receives respectively. That is, the sender should be blocked until the receiver receives the message, and the receive likewise should be blocked until the sender send the message.
2. Add the following "identification" operation:
GP x1x2GP puts the process id of the process into register R.
Shared Storage and a Semaphore Facility for Shared Memory Synchronization.
Create a special 100 location shared storage area that can be accessed
by any process using only the following two new operations:
| Operator | Operand | Interpretation |
|---|---|---|
| LS | x1x2 | R := [a]; |
| SS | x1x2 | [a] := R; |
LS stands for "load shared", and SS stands for "store shared". These operations are executed atomically.
In addition to the shared memory area, create an array of 100 semaphores numbered 00 - 99 and always available to any process. Provide the following two operations to operate on these semaphores:
PE x1x2PE acts atomically as a P, or "down" operation on the semaphore x1x2, VE acts as a V, or "up" operation, and SI initializes the designated semaphore (x1x2) to the current value of the register R. By default all semaphores have an initial value of 1.VE x1x2
SI x1x2
BRAIN02 Process Scheduling
The intention is that BRAIN02 process scheduling should be similar to the model of process scheduling presented in class. That is, ready BRAIN02 processes should be linked up in a circular queue (the ready list) and chosen one after another in a round robin manner.
A question arose in class as to how and when the kernel would switch between BRAIN02 processes. The answer was in two ways.
Do you have to rewrite your program 2 for program 3? The answer is "yes, to an extent", but you should be able to encapsulate the virtual machine accesses inside procedure calls, after which only the procedure implementations have to change. For example, if you addressed your 100 locations of memory with direct memory accesses such as:
MEM[99] = R andYou would then have to rewrite these calls as:R = MEM[30]
PHYSICAL_MEM[99 + offset] = R andwhere offset is the position (0,100,200,300,etc.) of the currently executing BRAIN02 process.R = PHYSICAL_MEM[30 + offset]
On the other hand, if you encapsulated this memory access inside procedure and function calls, the calls might look like this in both cases:
STORE_MEM(99,R) where the value of R is stored in virtual location 99, andIn these cases the value of offset can be a global variable that is managed by the kernel and that corresponds to the memory map stored in each process slot of the kernel discussed in class.R = LOAD_MEM(30) where R gets the value of the function LOAD_MEM from virtual location 30.
It is very much worthwhile to think first about the virtual machine implementation, and then think about how such a virtual machine runs on the physical machine. For this reason I broke the problem into 2 and 3.
In each of these cases, don't get carried away. We have lots of other things to do.
BRAIN02 Program Implementation and Analysis:
Implement and analyze the following BRAIN02 programs:
Attach a unique process number to each output line, designating
which process is printing which output. Designate a special process to
handle input, another to handle output, and then require any process who
wants to do input and output to send input and/or output messages to these
"server" processes. These processes may then do a limited amount of buffering.
Change in BRAIN02 Program Format
Recall that you entered BRAIN02 programs in project 3 in batch format. That is, you entered your BRAIN02 programs all at once from standard input before starting execution. For this project, store each BRAIN02 program on a disk file, and include at the beginning of this file a requested upper bound on your address space. This value may be any value from 0 up to the value of the upper bound on your physical address space.
Addition of "Spawn" instruction
Add a SPAWN instruction to your BRAIN02 interpretor.
SP x1x2where x1x2 is a two character filename residing locally with respect to the BRAIN02 executable.
This instruction will retrieve a named BRAIN02 program from disk, allocate memory for it, load it, and add it to the ready processes. Upon normal completion of the spawn operation, the parent R = the process ID of the child and the child R = the process ID of the parent. If no memory is available, then R = 0 upon spawn completion. Note: this means that the system doesn't halt if a process cannot be spawned. Instead, the process that is attempting to spawn is "told" of the problem (with an R = 0).
To test the "R=0" feature, create a BRAIN02 program RR that spawns itself as follows:
SPRRThis program has very interesting (emergent?) characteristics, which can vary depending on how you implement your scheduler:
SPRR
SPRR
SPRR
H
Implement your memory management scheme using two different memory allocation schemes (i.e., first fit, next fit, worst fit, best fit, etc...). You can do this with two different implementations, or by integrating them into one implementation and allowing the user to choose which method to use when the system is "booted up".
n and m should be parameters of your system to test the effect of varying page frame size. For example choose n=200 page frames and m=5 locations per page frame, then choose n=100 and m=10. Re-implement your memory management scheme of project 4 using a virtual memory scheme discussed in class.