Programming problems are to be done in your assigned groups using the VM that has been assigned to your group. For all programming problems you will be required to submit source code, a README file documenting your files and code, and a test run of your programs. For source code submissions, you only need to submit new source code files that you created and kernel source code files that you changed. You should clearly indicate your names, email addresses, and assigned group number on your submission. Each group is required to submit one writeup for the programming assignment using the SUBMIT program. Refer to the homework submission page on the class web site for additional submission instructions.
System calls allow unprivileged user-space programs to issue requests to the kernel for low-level procedures (device access, process signaling, etc.). Generally speaking, system calls form an operating system's interface. Most operating systems contain several hundred system calls and adding new ones should be part of any kernel hacker's toolkit. For this assignment we will learn how to both hard-code system calls into a kernel and use kernel modules to add new system calls at runtime.
This portion of the assignment consists of five parts.
/etc/lilo.conf
to allow you to boot your kernel.
struct proc_struct
as its arguments, and populates the
structure with the process state information for that process.
The prototype of the system call will be:
int proc_info(pid_t pid, struct proc_struct *proc);
pid_t
is defined in /usr/include/sys/types.h
.
You should define struct proc_struct
as
You should create a new filestruct proc_struct { pid_t pid; /* id of process */ pid_t parent_pid; /* process id of parent */ pid_t youngest_child_pid; /* pid of youngest child */ pid_t younger_sibling_pid; /* pid of younger sibling */ pid_t older_sibling_pid; /* pid of older sibling */ pid_t prev_pid; /* pid of prev process on run queue */ pid_t next_pid; /* pid of next process on run queue */ long priority; /* priority of process */ unsigned long rt_priority; /* real-time priority of process */ unsigned long policy; /* policy of process */ long state; /* state of process */ 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 */ int uid; /* user id of process */ int gid; /* group id of process */ char comm[16]; /* name of program executed */ };
include/linux/proc_info.h
in
which this structure is declared.
The definition of this system call should be added to the file
kernel/sched.c
.
Your system call should return 0 if it is able to locate the process information for the target pid. At a minimum, your system call should detect the following conditions and respond as described:
youngest_child_pid
should be set to -1 if the
process does not have a child.
The referenced error codes are defined as ESRCH and EINVAL,
respectively, in /usr/src/linux/asm/errno.h
.
Note that the majority of a Linux process's information is contained
within the task_struct
structure defined in
include/linux/sched.h
.
This structure is analogous to the Process Control Block mentioned in your
textbook. Two instances of task_struct
have special meaning: current
refers
to the process currently running and init_task
refers to the idle process that the system uses to waste processor
time. Both current
and init_task
may serve
as your primary anchorpoints when navigating the kernel.
Some references you might find useful are the Kernel Hacker's Guide, particularly the section on "How System Calls Work in Linux/i86", The Linux Kernel, and the optional class textbook, Linux Kernel Internals. In addition, Linux Journal recently had a very good article about Implementing System Calls.
In order to learn about kernel module programming, you should check out The Kernel Module Programmer's Guide as well as Loadable Kernel Modules.
proc_info
system
call. Your syscall will be declared through the use of a syscall macro as
follows:
Write a second version of this utility, for the_syscall2(int, proc_info,pid_t, pid, struct proc_struct *, proc);
proc_info2
system
call, and benchmark your two utilities against one another. Which method of
using a system call is faster? Why?
HINT:
In order to learn about system calls, you may find it helpful to
search the Linux kernel for other system calls and see how they are
defined. The file kernel/sched.c
might give
some useful examples of this. The getpid
and getuid
system calls might be
useful starting points.