Lab/HW: Fun with Processes

Objective

The purpose of this assignment is to acquaint you with the basic Posix system calls that manipulate processes.

Even though Linux is written primarily in C, Python allows us a simple way of making Posix system calls so we can concentrate on OS issues without worrying about arcane details of C pointers and strings. The python system calls page shows how some Posix system calls are done in Python. You can get information about system commands using the Linux man command. for example:

 $ man fork 
will tell you all about the fork system call. To see the Python documentation, you can invoke the pydoc command from the unix prompt:
 $ pydoc os.fork
Or use the help function inside an interactive Python session:
>>> import os 
>>> help(os.fork) 

The first 4 programs constitute a lab warm-up exercise and should be completed in teams of 2 to 3 students. The final problem is homework to be done individually.

Program 1: asbs

Write a program that comprises two processes. One process should write five thousand a's (lowercase "a") to the screen (with no new-line characters); the other process should write five thousand B's (uppercase "B"). Run the program and observe how the processes are scheduled. Note: if the a's and B's are not interleaved, you might have to increase the number that are written. Be sure to run your program several times before upping the counts, as scheduling may vary from one run to the next.

Here's a program, as1000.py that prints 1000 a's to the screen, this should help you get started. You can run the program by typing "python as1000.py" at the prompt. Note, this program makes use of sys.stdout to write it's output. This allows us to print a stream of a's one at a time without any spaces between.

Program 2: asbs2

Modify the asbs program so that it comprises three process. The initial program should create two child processes, one to print the a's and the other to print B's. The parent program should then wait until both children have completed before printing a message "all done" and exiting. This illustrates one method of Posix process synchronization.

Program 3: lullaby

Write a program that creates a sleepy child process. The child should: 1)print a message giving its process id 2)sleep for 10 seconds 3)print a message saying that it's terminating, and 4)terminate with status 13. The parent should: 1)print the process id of the child, 2)wait for the child to terminate, and 3)print a message showing the child's termination status. This illustrates one form of communication between processes.

Program 4: dateproc

Write a program that creates a child process to run program /bin/date and waits for the child to complete. (The /bin/date program prints the current date and time). You should be able to do this quite easily using the execl system call. This program is intended to prepare you for the next one.

Program 5: shell

One interesting feature of Unix is that it does not have a pre-specified user interface. Rather, progrmminers can write their own interface using the underlying system calls. Such a program is usually called a "shell". The face you see on Unix is determined by the shell you use. Common shells include csh (a c-like shell), the Bourne shell (written by Bourne), zsh, tcsh, Korn, and bash.

For this program, you will implement a shell of your own. Your program will 1)write a prompt to the screen, 2)read an input line consisting of a string of characters optionally followed by an ampersand ("&"), 3)create a child process that executes the program whose name was entered, and 4)if the line did not end with an ampersand, wait for the completion of the child. These steps should be in a loop that continues executing until the user types "exit".

The code for the main loop is in the file shell-shell.py. You need to complete this code by providing the the crucial execute function. As it stands now, this function just prints out its arguments.

Test your shell using the programs: /bin/date, asbs2, and sleep10 a program(that you must write) that sleeps for 10 seconds and then prints a message.

Once your shell is working, see if you can enhance it in a couple ways. If the program cannot be found, print the message "Command not found" (like most Unix shells). If a program is run in the background (i.e. with an "&") print its process number when it is created (again, like typical shells). Another enhancement would be to retry the command with a "./" prepended if it is not found initially. This allows programs in the current directory to be run by just typing the name of the command.

Here is an example interaction:

[zelle@neon cs360]$ ./myshell.py
john's shell%
john's shell% fooey
fooey command not found
john's shell% /bin/date
Wed Feb 11 19:42:16 CST 1998
john's shell% sleep10.py
*** sleep 10 program terminating ***
john's shell% 
john's shell% sleep10.py &
[1] 1734
john's shell% sleep10.py &
[2] 1735
john's shell% sleep10.py &
[3] 1736
john's shell% *** sleep 10 program terminating ***
*** sleep 10 program terminating ***
*** sleep 10 program terminating ***

john's shell% exit
[zelle@neon cs360]$ exit

Required Documentation
You should hand in the source code for each of your programs and an example of the output from the program. You can capture output either by running the programs inside of Emacs (using -x shell) or with the Linux script command (try: "man script" for details). Again, the first four programs will be done as a lab, the shell program is homework.

* * * * IMPORTANT IMPORTANT IMPORTANT * * * *

As you are working on this assignment, make sure to do a "ps" to see if you left any orphaned processes before you logout. You can kill them off with the kill command. Please make every effort to keep the system free of stray processes.

If you forgot to check before logging out, you can see all of the processes that you own (including those created in a previous session) by doing a "ps -x". If you're curious, "ps -aux" will show all of the process with information about ownership and status. Of course, you can't kill processes that you don't own.