Due by 11:59 p.m., Monday, October 12th, 2009.
Please use the class discussion board (you can find it on your blackboard) as a communication and Q&A tool. Should you still need to send an e-mail inquiry, address it to the TA (Hongzhou Zhao: hozhao@cs...) and cc the instructor. This assignment will be examined through demo with the TA. The demo time should be conducted with the TA by the due date or earlier. We expect that each demo will take 20-30 minutes. Please reserve your time slot with the TA ahead of time.
This is a group assignment. You should form a group of two to complete this assignment. We urge you to establish safe and flexible policies for managing your code with your group member as soon as possible. A versioning tool would come in handy. You are encouraged to help (and seek help from) people in other groups (except sharing code, of course). Note that we will not distinguish grades within a group. but corrective action could be taken if inequitable load distribution is noted.
Disclaimer: This assignment is adapted from a project developed by Dr. Jason Nieh at Columbia University.
Write a new system call in Linux. The system call you write should
take one argument (pointer to a data structure) and return various
information for the process identified by the pid in the
data structure. All return information will be put into the data
structure. For the following discussion all relative paths refer to the
top of your kernel source directory linux-2.6.26.5
The prototype for your system call will be:
int prinfo(struct prinfo *info);
You can define struct prinfo as
struct prinfo {in
long state; /* current state of process */
long nice; /* process nice value */
pid_t pid; /* process id (input) */
pid_t parent_pid; /* process id of parent */
pid_t youngest_child_pid; /* process id of youngest child */
pid_t younger_sibling_pid; /* pid of the oldest among younger siblings */
pid_t older_sibling_pid; /* pid of the youngest among older siblings */
unsigned long start_time; /* process start time */
long user_time; /* CPU time spent in user mode */
long sys_time; /* CPU time spent in system mode */
long cutime; /* total user time of children */
long cstime; /* total system time of children */
long uid; /* user id of process owner */
char comm[16]; /* name of program executed */
};
include/linux/prinfo.h as
part of your solution. Note that pid_t
is defined in include/linux/types.h.
Sibling processes are those sharing the same parent. Young/old
comparison between processes are made based their start time.
Each system call must be assigned a number. You can use any that is
not yet used by the kernel. Your system call should return 0 unless an
error occurs. Your code should handle errors that can occur but not
handle any errors that cannot occur. At a minimum, your system call
should detect whether the input prinfo
structure is null and return -22 if so. The referenced error code is
defined as EINVAL in include/asm/errno.h.
Hint: Linux maintains a list of all processes in a doubly
linked list. Each entry in this list is a task_struct structure, which is
defined in include/linux/sched.h.
In include/asm/current.h, current is defined as an inline
function which returns the address of the task_struct of the currently running
process. All of the information to be returned in the prinfo structure can be determined
by starting with current.
Another Hint: In order to learn about system calls, you may
also find it helpful to search the Linux kernel for other system calls
and see how they are defined. The file kernel/timer.c
might give some useful examples of this. The getpid system call might be a useful
starting point. The system call sys_getpid
defined in kernel/timer.c uses
current and provides a good reference point for defining
your system call.
To test your system call, write a simple program that calls the prinfo system call with an input
pid. Your program should print all the process state information for
the calling process. Run the program several times. Which fields in the
prinfo structure do not change?
Which ones do and how frequent? Prepare the answers in a writeup before
the demo.
Although system calls are generally accessed through a library
(libc), your test program should access your system call directly. This
is accomplished by utilizing the syscall
macro in /usr/include/unistd.h.
Read the Adding a new system call to the Linux kernel document to see
an example on how to proceed.
The output of the program should be easy to read. The ps
command will provide valuable help in verifying the accuracy of
information printed by your program. You can access detailed
information on the ps command by entering man ps.
A Linux kernel reference book would be very helpful. For instance, Chapter 4 of the Linux Kernel Development book gives detailed instructions on building a system call. You will definitely also find online help on this.
Hopefully, the move to QEMU as a testbed for our Linux development
will make your life much easier in terms of debugging. See the
respective introductory notes for debugging ideas. For the most part
though, you can just use printk
to print out stuff inside the kernel. To request printk messages be sent to a log
file, insert the following line into the /etc/syslog.conf file:
kern.* /var/log/kern.logThis will cause
printk
messages to be written to /var/log/kern.log
after next reboot.
Have fun hacking!!!