Due by 11:59 p.m., Wednesday, September 26th, 2012.
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 (Brandon Shroyer: bshroyer at cs ) and cc the instructor. The group part of 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.
The latter part of this assignment 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 generally distinguish grades within a group. but corrective action could be taken if inequitable load distribution is noted.
Disclaimer: Part of this assignment is adapted from a project developed by Dr. Jason Nieh at Columbia University.
The goal of this assignment is to get you thinking about the costs of various system calls. This part of the assignment is an individual assignment. However, you are encouraged to help (and to seek help from) your peers (except sharing code, of course). For many of the following measurements, you may need to repeat the experiment many times and then take the average. Use a high resolution timer for x86 when necessary. The goal is to have STABLE measurement results. For some of the questions, I will provide a possible measurement strategy as a hint. You are encouraged to be innovative in designing your own test. Extra credit will be given for such innovations that also (of course) work. For comparison purposes, all measurements MUST be done on machines in the graduate software lab or the CSUG lab.
X seconds). The minimal cost can be emulated by measuring
a bare function call that neither takes any parameter nor does anything
inside the function. Hint: Be careful to avoid including loop overhead.
getpid().
pipe system call).
Additional note about performance measurement: You should be careful with your measurement methodology. You may want to take into account things like loop overhead and timer overhead (making calls to start and stop the timer can induce costs that are non-negligible when measuring the cost of a single function call). For the pthreads part, you should be careful about how you include thread creation overhead as well as where you insert your timing calls in order to determine both overall and breakdown timings.
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.
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 provide 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 specified pid. Run the program several times. Which fields in the
prinfo structure do not change?
Which ones do and how frequently? 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 (second edition) 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 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 with it!!!
Turn-in:
You are asked to electronically turn in your source files and a makefile.
Attach a README file describing the name of the executable,
special compiling instructions, or anything else special you want to let us
know. Also include your measurements in this README.
The README file should be in plain text format. Instructions
for electronic turn-in can be found on the class web page.
Late turn-in policy:
Late turn-ins will be accepted for up to three days, with 10% penalty for each
late day.
No turn-ins more than three days late will be accepted.