(Some parts of this section have been summarized from the Linux signal(7) man page)
A signal is an event which can be sent by one process to another process. Each signal has a current disposition, which determines how the process behaves when it is delivered the signal.
The following default actions are available:
There are a number of standard signals that are supported by most UNIX-like OSs, for example SIGHUP, SIGINT, SIGQUIT, SIGKILL, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, and SIGUSR2. You can take a look at the signals(7) man page for more details on these signals. There are others listed on the man page as well.
A process can change the action of a signal using the signal() system call. Using this system call, a process can elect one of the following behaviors to occur on delivery of the signal: perform the default action; ignore the signal; or catch the signal with a signal handler, a programmer-defined function that is automatically invoked when the signal is delivered.
Extend the xv6 kernel to add support for process signals. For this homework assignment, you must modify the xv6 kernel to allow for "user-level signals" to be posted to processes. Additionally, you must implement three new syscalls. These syscalls (as further described below) will add support for a process to (i) register a custom handler for each signal, (ii) issue a signal to itself, its parent, or any of its child processes, and (iii) get the process id of its parent process. Finally, as part of this assignment, you will be required to create an xv6 program that both establishes a custom signal handler in a parent process and issues a signal from a child to its parent that triggers the parent's handler.
Here are the steps you will need to complete for this assignment:
1. Add support for 16 signals (numbered 0 through 15). Each process should be able to register its own signal handler for each of these 16 signals.
2. Add a new system call: int getppid(void). The getppid() system call takes no arguments. When called it returns the process id of the calling process' parent.
3. Add a new system call: int signal(int signum, sighandler_t handler). The signal() call takes the signal number (signum) and a pointer to the signal handler (handler) as arguments. It returns the previous value of the signal handler on success or -1 on failure. The parameter "handler" is of type sighandler_t, which you will have to define as typedef void (sighandler_t)(void) at appropriate places in the source code. When called by a process, the signal() system call should register "handler" as the signal handler for signal "signum" for that process.
4. Add a new system call: int kill_signal(int pid, int signum). The kill_signal() call should take a process id and a signal number as arguments. It should return 0 on success or -1 on failure. A process may access its own process id via a call to getpid(). It may access its parent's process id via a call to getppic() (see #2 above). Also, fork() returns the process id of child processes to the parent (as the return value). When called by a process, the kill_signal() system call should post a "signum" signal to process "pid".
5. Create a user-level test program called kill_test that sets a custom signal handler for a signal to print output to the screen. Then it should fork a child process and wait. The child process signal its parent and then exit. The parent should process the signal and then exit afterwards. The way to do this is to have the parent's custom signal handler also set a flag that breaks its waiting condition so that it can only exit after receiving the signal from its child.
XV6 SOURCE CODE: The source code for the xv6 kernel can be downloaded from here.
This section is a list of hints for some of the more difficult portions of the assignment. This does not cover every aspect of the code changes that must be made, though.
Email the tar file to your TA prior to the deadline. The subject of the email should read "[CS416-S08 HW#3]". Please ensure that you submit the files before the deadline. To be safe, hand it in as early as possible. If you are close to the due date/time and are not completed, you can submit one version with whatever you have done earlier, and then submit a later version by sending a new tarfile before the deadline. We will consider the submitted version to be the last version received, prior to the deadline.