Computer Science 330
Operating Systems
Fall 2025, Siena University
In this lab, you will learn about some Unix operating system mechanisms that support interprocess communication.
You must work individually on this lab.
Learning goals:
Getting Set Up
In Canvas, you will find a link to follow to set up your GitHub repository, which will be named ipc-lab-yourgitname, for this lab.
Answers to written questions may be given in a PDF document committed and pushed to your repository (give the name in the README.md file), by writing them in a readable (reasonably nicely formatted, not all one big line of text) GitHub Markdown form in your repository's README.md file, or by linking to a shared document containing your answers from your README.md file.
Examples related to this lab are in
https://github.com/SienaCSISOperatingSystems/sysprog-examples
(same as in the previous lab).
Pipes
Processes may wish to send data streams (sequences of bytes) to each
other. Unix pipes are one way to achieve this. You've almost
certainly used Unix pipes at the command line. All modern Unix shells
allow you to specify multiple commands on the same command line with
| symbols in between. This indicates that these programs
should be running at the same time, and that the output of a program
in any (except the last) program in the pipeline should be "piped"
to be the input of the subsequent program in the pipeline.
For example, the command line
ls | wc
runs the ls and the wc ("word count") programs, piping
the output of ls to be the input of wc.
grep ^q /usr/share/dict/words | wc -l
grep -i dan namelist.txt | sort | tail -3
Using Pipes in C Programs
Turns out, you can also use pipes directly in programs. Which is a good thing, since Unix shells that support this are just C programs.
An unnamed pipe can be created using the pipe(2) system
call.
We consider the example programs in the pipes directory. pipe1.c is an example of communication between two processes, a parent and its child created by fork(), communicating via an unnamed pipe.
We can create a named pipe or fifo at the command
command line with mkfifo(1) or in a program with mkfifo(2).
pipe2.c augments our simple example using a named pipe.
Run two instances of this program in two different windows, one to read, one to write.
Duplicating file descriptors
We can use the dup2(2) system call to "reroute" input or output from one file descriptor to another file descriptor. This is how your I/O redirection and pipes will work in the shell project.
Back in the exec directory of the sysprog-examples repository, see and try execredir.c.
We have seen that you can also obtain file descriptors from open(2) and pipe(2). The file descriptors at the ends of a pipe can be passed to dup2(2) as well - this will be useful in the shell - set the output of one process to be the input of another through a pipe.
Signals
We next consider a form of interprocess communication in a Unix system known as signals.
kill -SIGSOMETHING pid
For example, if we launch a program at our Unix prompt to sleep for 60 seconds and put it into the background:
-> sleep 60 &
you should see output something like:
[1] 96132
where "96132" would be the process id of the sleep process you just created, and [1] is the job number within your Unix shell of the process.
We can then send signals to that process by using its pid or %1
which will refer to job number 1.
For example:
-> kill -TERM %1
will send the SIGTERM signal to try to terminate the process. If you do this, you should see output similar to:
[1]+ Terminated sleep 60
Now launch another sleep 60 process in the background. Assuming this becomes shell job 1, issue these commands:
-> kill -STOP %1 -> kill -CONT %1
and wait until the sleep command finishes.
A default signal handler is installed when a process begins. signal(2) replaces default handler. This lets you trap many signals and handle them appropriately.
Be careful not to confuse this signal() with the "signal" operation on semaphores! Unrelated.
We consider the example programs in the signals directory. The sigalrm-example.c example is compute-bound process that "wakes up" every 5 seconds to report on its progress.
The setitimer(2) system call is used to set a "timer" which will cause a SIGALRM signal to be sent to the process at some time in the future (in this case, every 5 seconds).
Consider this enhanced example: sigalrm-example2.c
Final note about signals: SIGCHLD will be useful for your shell projects. This is the signal that gets sent to a process's parent when the (child) process terminates.
Submission
Commit and push!
Grading
This assignment will be graded out of 35 points.
|
Feature | Value | Score |
| Question 1 | 1 | |
| Question 2 | 2 | |
| Question 3 | 3 | |
| Question 4 | 1 | |
| Question 5 | 1 | |
| Question 6 | 2 | |
| Question 7 | 3 | |
| Question 8 | 1 | |
| Question 9 | 1 | |
| Question 10 | 1 | |
| Question 11 | 1 | |
| Question 12 | 1 | |
| Question 13 | 1 | |
| Question 14 | 2 | |
| Question 15 | 2 | |
| Question 16 | 1 | |
| Question 17 | 1 | |
| Question 18 | 2 | |
| Question 19 | 1 | |
| Question 20 | 1 | |
| Question 21 | 2 | |
| Question 22 | 1 | |
| Question 23 | 3 | |
| Total | 35 | |