Homework 2 -- Programming

Administrivia

This is a group assignment, per the instructions given at the beginning of the semester. Turn in one copy of the programming assignment; however, each of you must turn in individual written assignments.

In addition, each team member must turn in the group programming evaluation with their own written assignments.

Deliverables

You're going to be modifying a kernel. We do not want you to submit an entire kernel source tree; instead, you'll submit the output of "diff" -- the differences between your code and the original. You'll also need to submit a working or a non-working cover sheet. Finally, turn in any test programs or data, a README file documenting your work (including clear explanations of what each file is), and output from test runs.

Adding a System Call

(90 points) The assignment is to add a new system call to the Linux kernel. There are two parts to the assignment.

Building and Booting a Kerne

(10 points) The first step is to build and boot an unmodified Linux kernel. There are enough unusual steps in the process that this would be worth doing even if it were not required — but it is.

To make life simpler for the next step, build your kernel from a copy of the downloaded tree. Of course, you shouldn't actually make a full copy; the kernel is about 221M bytes, in almost 19000 files. Instead, do

cp -al linux-2.6.8.1 linux-2.6.8.1-xyzzy
where -al means "create a link" instead of actually copying the data. xyzzy is some unique string, such as your UNI.

Editing the Source

Remember that your source tree is just a set of links to the original. You do not want to edit the original; if nothing else, you won't be able to run diff on it. What to do depends on what editor you use. If you're an emacs user, you have no problem; emacs will rename the original and create a new file for the edited version. If you're a vi user, though, you'll have to do it yourself. Run mv file file.orig; cp file.orig file before you invoke the editor.

Adding a System Call

Your task is to add a system call getprocinfo(pid_t pid, struct procinfo *inf) that returns the following data about the specified process:

struct procinfo {
    pid_t pid;                    /* Process ID */
    pit_t ppid;                   /* Parent process ID */
    struct timespec start_time;   /* Process start time */
    int num_sib;                  /* Number of siblings */
};
You can find all of the information you need in task_struct, which is defined in include/linux/sched.h.

If pid is greater than 0, it represents a processID who's information is sought. If it's zero, return the information for the current process. If it's less than zero, return the information for the parent of the current process.

As always, check inputs for validity. Return error EINVAL if necessary.

You'll find it useful to look at the kill system call; see sys_kill in kernel/signal.h. Also see sys_getpid in kernel/timer.c.

You need to create a system call entry, as discussed in class; use number 223, which is currently unused. You'll also need to create a function getprocinfo() that is called by your test programs.

I was asked about the user-level code to invoke a system call. It occurred to me, belatedly, that I'd told you to download kernels and not user-level code. It took me a remarkably long time to find examples; when I did, it was by asking a friend... Accordingly, I wrote my own. You can find mystat(), an implementation of the fstat() syscall interface, and a main program that invokes it. I compiled and tested them on a CLIC machine.

To generate diff output, use

diff -Naur linux-2.6.8.1 linux-2.6.8.1-xyzzy

Your vmware directory is not backed up. For safety's sake, make a copy of your changes — not the whole kernel tree! — on another machine.

Danger, Will Robinson

If two people boot the same virtual machine at the same time, it will corrupt the (virtual) disk. Please co-ordinate usage with other members of your team.