CPSC 457: Operating Systems

Professor Carey Williamson

Fall 2008

Assignment 2 Tips

I know that this assignment may look a bit intimidating, particularly once you start wading through the Linux kernel source code for UML, but it is actually doable with what you know already from CPSC 457.

The most important pieces of general advice are:

Enough of the high-level motherhood principles. How about some real tips?

Here are some from my own weekend spent in the lab, working with UML and Linux 2.6.24.

To get a brand new clean version of UML, run 457-init:
    /usr/uml/457-init

To start up UML, do the following:
    cd /tmp/YOURNAME/uml
    ./startuml

To login as root in UML, simply type "root" to the login prompt on one of the UML windows. (There is no password required for root.)

To make your existing home directory of student files accessible to you from within UML, use the mount command like this:
    mkdir /host
    mount none /host -t hostfs -o YOURHOMEDIRECTORY
    cd /host
    cd ONEOFYOURDIRECTORIES

To create a new user named "fred" within UML, do the following:
    useradd fred
This should create a new entry in the /etc/passwd file, along with an assigned user id number, and a new home directory in /home. As superuser, you can edit the password file to make the login password null (empty), so that you can login to a UML window as fred with no password. Or you can have fred use the passwd command to set a desired password. You can use the "su" command to switch back and forth between your different user identities in UML (root or fred), or you can use one of the login windows for each.

You can now create and edit files as fred if you wish, or you as superuser can copy some files to fred's directory using:
    cp YOURDIRECTORY/looper.c /home/fred/
    chown fred /home/fred/looper.c
Fred should now be able to compile and run the looper program. You can use ps to check the status of the executing process, either as fred or as superuser.

To shut down your current UML session, from your root window run:
    shutdown -h now
This should gracefully terminate UML and close all active windows.

If you are ready to modify some kernel code, then the following will be useful for you. (Note that this is done from outside the UML environment.)
    cd /tmp/YOURNAME/uml/linux/kernel
    cp sched.c schedsave.c
    emacs sched.c
    cd ..
    make linux ARCH=um CC=gcc CXX=g++
Watch for any kernel compilation errors. Fix any that arise. If the kernel compiles successfully, you should be able to:
    cd ..
    ./startuml
and run your new Linux kernel!

If you want to be sure the kernel is running your code, you can put some printk() statements in selected places. (Example: printk("Yo dude!"); ) By default, printk() messages will appear on the console, which is usually the first (root) of the four login windows that UML creates. You can also use the dmesg command to view the message log. It is best to keep your printk() messages brief, as there will probably be a lot more of them than you expect!

If you are trying to modify kernel system calls, then these are some useful files to know about:
    /tmp/YOURNAME/uml/linux/include/asm/arch/unistd_32.h
    /tmp/YOURNAME/uml/linux/arch/x86/kernel/syscall_table_32.S
    /tmp/YOURNAME/uml/linux/arch/um/kernel/syscall.c
    /tmp/YOURNAME/uml/linux/arch/um/include/syscall.h
For example, you should be able to install a "Hello world!" system call like the TAs described in the tutorials.

If you are trying to modify the CPU scheduler itself, then these are some useful files to know about:
    /tmp/YOURNAME/uml/linux/include/linux/sched.h     (see line 917)
    /tmp/YOURNAME/uml/linux/kernel/sched.c     (see line 3617)
    /tmp/YOURNAME/uml/linux/kernel/sched_fair.c
    /tmp/YOURNAME/uml/linux/arch/x86/kernel/process_32.c
    /tmp/YOURNAME/uml/linux/kernel/fork.c

One good starting point is to have the schedule() function in sched.c print out a message whenever it sees a process owned by fred. Set this up, boot the kernel, and see what happens when fred logs in.

Another fun trick is to change the default scheduling priority for processes owned by fred. One possible place to do this is in the do_fork() routine in fork.c. Set this up, boot the kernel, and use ps to see the status of processes launched by fred. Try lower values and higher values to see what happens.

Here are some updated tips for those who need it.

Unix and Linux systems have a "nice" command that allows a user to voluntarily designate a lower priority for a process that they are submitting for execution. For example, "sleep 60" runs at normal priority, while "nice sleep 60" runs at slightly worsened priority. Do a "man nice" to learn more about nice.

Then take a very careful look at how the nice command is implemented in the kernel. You basically want to do the same to implement your own command (evil?), which has three differences from nice. First, it is the evil superuser who is adjusting the niceness level for the user, rather than the user themself. Second, you can adjust niceness to any arbitrary value (upward or downwards). Third, you can set this up for any FUTURE processes created by that user, rather than just a single currently running process.

Try having the SAME user (e.g., fred) run MULTIPLE processes concurrently with different nice levels. If one of the running processes has pid 12345, then do a "cat /proc/12345/sched" to see detailed information about the process (e.g., priority level, running time, scheduling load weight). See if it has the values you expected. Look at the "prio_to_weight[]" table in the kernel to see if things make sense to you.

Try having DIFFERENT users (e.g., ari and carey) run processes concurrently with different nice levels. If one of the running processes has pid 12345, then do a "cat /proc/12345/sched" to see detailed information about the process (e.g., priority level, running time, scheduling load weight). See if it has the values you expected.

If things are still not working right at this point, then it is probably the CFS (Completely Fair Scheduler) CPU scheduler in Linux that is messing you up, by being completely fair to all user processes. Look for a way to disable this scheduler (Hint: see the autoconf.h file). Note that you will have to COMPLETELY recompile your kernel to have this change take effect.