Basic OS Infrastructure

Project Due Date: Thursday, February 7 by 11:59 PM

Updates and Notes

2/7: Handin directory: should be ~cs537-1/handin/username/p1, not just ~cs537-1/handin/username (as specified earlier)

2/7: Demos will be held in 1358, barring further notice.

2/6: Demos are on Friday, February 8th. You can now sign up for one here.

2/6: Pipes/FIFOs: All fifo files should be created in /tmp. If you are creating

2/5: The Sun Answerbook may be more useful than man pages for some of you. Check it out.

2/4: You can safely assume that no line will be longer than 256 characters. Extra: Make your program work on input lines of any length (for pride, not points)

2/2: Please use the mailing list cs537-question@cs to ask questions about the project. All such questions and their responses will be logged here. Please feel free to peruse the questions so as to get your question answered without asking us.

1/30: The sample input file has been embellished with a few extra comments. Look here for details.

1/30: A new section has been added below on "other useful library calls"; look below for details.

1/30: A new subsection called "A note about Pipes" has been added below as well.

Objective

Welcome to Project 1! (The nightmare begins) The basic purpose of this assignment is two-fold: 1) to familiarize you with the basics of C programming, including syntax and more difficult concepts such as pointers, and 2) to get you acquainted with "systems programming". To accomplish the former, you will write code that creates and manages a sorted linked list. To accomplish the latter, you will write this list-management code as a part of a set of programs that communicate with each other via inter-process communication (IPC).

This project serves as a basic foundation for the rest of the projects, all of which are based around the concept of building what is called a "user-level micro-kernel." More specifically, you will be building a program that acts as a kind of "operating system" to other processes, providing typical OS services such as a file system, scheduling, and the like to other processes via IPC (more details on this will be given in future assignments). Some of the code you create here may be used in these future assignments, so you should put together a reasonable design before beginning the project, and then put together as modular and robust of an implementation as you can.

Project Description

This project is to be done alone. It is OK to talk to others about it, but no sharing of code is allowed.

This project should be done on Solaris-based machines (the Nova lab). It is OK to develop on Linux or other Unix-based OS's, but if it does not work on Solaris, you are out of luck.

You will be required to write two separate programs. One program generates simple requests, and the other accepts these requests via IPC and then puts them into a list. The names of these two programs should be process.c and os.c (it is OK if the names are process.cc and os.cc for those using C++).

The first program, process.c, should read integers from a file and communicate them to the second program, os.c. This communication will be done by means of interprocess communication. The means of facilitating this communication will be discussed in detail in the next section. The data being extracted from the file by process.c should be checked for correctness. Any invalid data should simply be ignored. No error messages should be printed and the program should not terminate. The program should most definitely not crash from the introduction of such invalid data. The program should just go on to the next line of data as if nothing had happened. A sample data file is provided here. When the last piece of data has been read by process.c, the program should send an END message to os.c indicating no more data is to be expected.

The os.c program should accept the integers communicated from process.c and place them into a linked list data structure in ascending order. It should also record the time at which each integer was received. The timer should not start until the first message is received. In other words, the first message received will always be at time zero. All the other times will be relative to this. Times should be given in milliseconds. Upon receipt of the END message, os.c should print out the following information to the standard output:

A sample of the output is provided here. This output file is for the data file shown previously. The times are completely made up and should not be considered indicative of your program.

You should NOT hard code the name of the FIFO file into your code (for more information on what this means, read the next section). Rather, both programs should accept the name of the FIFO file to communicate through as one of the command line options. This will allow us to create any arbitrary FIFO file and make your program communicate through it.

Additionally, the process.c program should accept the name of the file to read data from. The following are the sample usages for both of the programs you right. Your program executables should both be named exactly as shown here:

process fifoFile dataFile
os fifoFile

Interprocess Communication (IPC)

Before describing one way to do IPC, it should be made clear that if you have a preferred method for communicating between processes (pipes, sockets, etc.), feel free to use that method. The method that will be presented in this section is named pipes. This is often referred to as FIFO communication.

Basic Idea
A named pipe is really just a special kind of file (a FIFO file) on the local hard drive. Unlike a regular file, a FIFO file does not contain any user information. Instead, it allows two or more processes to communicate with each other by reading/writing to/from this file.

Creating a FIFO File
The easiest way to create a FIFO file is to use the mkfifo command. This command is part of the standard Linux utilities and can simply be typed at the command prompt of your shell. You may also use the mknod command to accomplish the same thing. This command requires an additional argument but otherwise it works pretty much the same. To learn more about these commands check out the man pages on them (just type man mkfifo or man mknod at the shell command prompt). The following example shows one way to use the mkfifo command:

prompt> mkfifo /tmp/myFIFO
That's it! It's pretty simple to set a file up for FIFO. There is also a system call that allows you to do this so you can put it in a program. You can read about that on your own if you would like.

Using a FIFO File
Using a FIFO file is slightly more difficult than creating one but not much - once you get familiar with how to make system calls. Because this named pipe looks like a file, you can use all the system calls associated with files to interact with it. In particular, you can use the open, read, write, and close system calls. The following are prototypes for each of these calls as you will need to use them.

To understand better what each of the return values and parameters are for, check each of these system calls out by looking at their respective man pages. Be sure to use the 2nd level of the man pages (on Linux, type man 2 open, and on Solaris, man -s 2 open, for example); otherwise, you may see something quite different than what you expect.

To give you an idea of how all of these can work together, here is a brief snippet showing how a sender might set up a connection and send a message.

Reading from the pipe is very similar. You need to open it up, use the read call to read information, and then close the pipe when everything is finished. More details on this process can be found on-line or by browsing various man pages.

A note about Pipes
A pipe must be opened for both reading AND writing before an open on either end will return from the open call, i.e., open will wait until the connection is setup between the two processes. This info can be found in the man page for open. It can be accessed by typing '/usr/bin/man -s 2 open' or '/s/std/bin/man -A open' on any Solaris machine in the department.

The other calls necessary for this project, read and write, also behave slighly differently with FIFO's. We would recommend reading their man pages also if you are having problems.

Other Useful Library Calls

To parse the input file, you may need to use a couple of different library functions. Here is a list you may find handy: read the man pages for more details.

Error Checking

Part of your overall grade will be based on your programs' robustness. This means error checking and handling. The checking of valid data in the input file presented to process has already been discussed. Besides this, your program should make sure to validate the command line presented by the user. If an error is detected, a message displaying the proper usage should be printed and the program terminated. All system calls should also be checked for a valid return value. If an error is detected, it should be handled appropriately. For example, if the user enters a FIFO file that does not exist, your program should indicate this error and terminate. Obviously the sample code provided above does not do this. Your code should.

Grading

No late assignments will be accepted. This project is due on Thursday 11:59 PM on February 7. This assignment will be graded based on correctness of implementation as well as robustness. To this end, we will not just be looking at the output of your program, but also the code. Points will also be deducted if all the proper files are not submitted. In this case, the mininum files will be process.c, os.c, a Makefile, and a README file describing your program.

Handing in Your Project

The directory for handing in your program can be found at:

~cs537-1/handin/(username)/p1

where (username) is your login.

Obviously, you should submit all *.c and *.h files that are needed to compile your program. You should also include a README file and a Makefile for this project. Your README file should contain information about how to run your program, any known bugs it may have, and any other information that is important to your project. Your make file should successfully compile the program and create the process and os executables.

Also, be sure to comment your code well so that it can be easily browsed to see what is going on. Code that is excessively difficult to read will be penalized.