Homework 1
CS W4118 Fall 1999
DUE: Wednesday, 10/6/99 at the beginning of class

CS4118 - Homework 1


Individual problems are due at the beginning of class on 10/6/99, with the usual homework deadline rules for CVN students in effect. Group programming problems are to be electronically submitted by 1:00am on 10/6/99, with hardcopies writeups due at the beginning of class on 10/6/99. The deadline for group programming problems applies to both CVN and non-CVN students. Refer to the homework policy page on the class web site for further details.

Individual Problems:

Individual problems are to be done individually. Exercise numbers refer to the Silverschatz and Galvin textbook. Each problem is worth 3 points unless otherwise indicated.

  1. Exercise 1.1
  2. Exercise 1.4
  3. Exercise 1.7
  4. Exercise 2.3
  5. Exercise 2.5
  6. Exercise 2.6
  7. Exercise 2.8
  8. Exercise 3.1
  9. Exercise 3.2
  10. Exercise 3.3
  11. Exercise 3.4
  12. (7 pts.) Write a trivial shell that reads a line from the standard input, splits the line into program name and arguments, and invokes the command after forking, with the arguments passed in the normal C manner. The shell waits until the program completes. You should write this in C. You can make reasonable assumptions about the maximum number of command line arguments.

Group Programming Problems:

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.

You will build your own Linux kernel for this class. For each homework assignment, you will build a new Linux kernel. The image of the kernel you build for this assignment should be vmlinuz.hmwk1. Grading for this assignment will be done based on vmlinuz.hmwk1.

  1. (8 pts.) Compile and install your own Linux kernel on your VM. To ensure that you can recover from problems with your kernel, do not overwrite the existing Linux kernel image. Instead, create a new kernel image that you can boot from using LILO. For this assignment, the image of the kernel you build should be named vmlinuz.hmwk1. Configure /etc/lilo.conf to allow you to boot your hmwk1 kernel.

  2. (5 pts.) The command "uname -a" provides information the the Linux kernel that is running. Change the test kernel that you compiled so that the output of "uname -a" also lists the group number of your assigned group.

  3. (30 pts.) The Linux kernel maintains state for each process as it executes. A process is identified by a process id number called a PID. Write a new system call in Linux that takes a PID as an argument, and returns the process state information for that process.

    The prototype for your system call will be:

    	int pinfo(pid_t pid, struct pinfo *info);
    
    pid_t is defined in /usr/include/sys/types.h. You should define struct pinfo as

    struct pinfo {
    	int pid;			/* process id */
    	long state;			/* current state of process */
    	long priority;			/* process priority */
    	int parent_pid;			/* process id of parent */
    	int youngest_child_pid;		/* pid of youngest child */
    	int younger_sibling_pid;	/* pid of younger sibling */
    	int older_sibling_pid;		/* pid of older sibling */
    	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 avg_slice;			/* average cpu slice */
    	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 */
    };
    

    in /usr/src/linux/include/linux/pinfo.h as part of your solution.

    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:

    The referenced error codes are defined as ESRCH and EINVAL, respectively, in /usr/src/linux/asm/errno.h

    You should start by reviewing the "How System Calls Work in Linux/i86" section of the Linux Kernel Hacker's (LKH) Guide. Note that because the Linux kernel changes over time, the procedure is no longer exactly correct. However, there are messages appended at the end of the section that will help significantly.

    You may also want to review the "Processes" section of The Linux Kernel.

    As explained in the LKH guide, each system call must be assigned a number. Your system call should be assigned number 191.

    Big 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 /usr/src/linux/include/linux/sched.h. In /usr/src/linux/include/asm/current.h, current is defined to inline a function which returns the address of the task_struct of the currently running process. All of the information to be returned in the pinfo structure can be determined by starting with current.

    Bigger Hint: The system call sys_getpid defined in /usr/src/linux/kernel/sched.c uses current and provides a good reference point for defining your system call.

  4. (17 pts.) To test your system call, write a C program that takes a PID as an argument and finds all the ancestors of that process. Your program should print the process state information for the specified process and for each of the ancestors of the specified PID. The information for the process and its ancestors should be printed in generational order, starting with the oldest ancestor.

    NOTE: 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 appropriate _syscall macro in /usr/src/linux/include/asm/unistd.h. As explained in LKH, which _syscall macro you use is determined by the number of arguments passed to your system call.

    The output of the program should be easy to read, and the program should check for errors such as invalid input or too many/few arguments, and invalid PID. 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.

    Your writeup should include the program output from the following two testcases: