Process Scheduling

Process Scheduling

Like many dialects of UNIX, the process scheduler is a function inside the kernel, not a separate process. Actually, it’s better to say that process scheduling is done by two functions working together, both of which are a part of sched.c. The first function is schedule(), which does the actual scheduling. The other is do_timer(), which is called at different times and whose function is to update the times of each process. Essentially, this is used to keep track of how long each process has been running, how long it has had the processors, how long it has been in user mode, how long it has been in kernel mode, etc.

In the section on operating system basics, I mentioned that each process gets a time slice that’s 1/100th of a second long. At the end of each time slice, the do_timer() function is called and priorities are recalculated. Each time a system call returns to user mode, do_timer() is also called to update the times.

Scheduling processes is not as easy as finding the process that has been waiting the longest. Some operating systems do this kind of scheduling, which is referred to as “round-robin.” The processes could be thought of as sitting in a circle. The scheduling algorithm could then be though of as a pointer that moves around the circle, getting to each process in turn. The Linux scheduler does a modified version of round-robin scheduling, however, so that processes with a higher priority get to run more often and longer.

Linux also allows you to be nice to your fellow processes. If you feel that your work is not as important as someone else’s, you might want to consider being nice to them. This is done with the nice command, the syntax of which is

nice <nice_value> <command>

For example, if you wanted to run the date command with a lower priority, you could run it like this:

nice -10 date

This decreases the start priority of the date command by 10. Nice values range from 19 (lowest priority) to -20 (highest priority). Note that only root can increase a process’ priority, that is, use a negative nice value. The nice value only affects running processes, but child processes inherit the nice value of their parent. By default, processes that users start have a nice value of 20.

The numeric value calculated for the priority is the opposite of what we normally think of as priority. A better way of thinking about it is like the pull-down number tickets you get at the ice cream store. The lower the number, the sooner you’ll be served. So it is for processes as well.

Although the nice command only works when you start a process, you can change the nice value on a running process by using the renice command. It uses the same priorities as nice, but is used on processes that are already running. It can take the -p option for a specific PID, the -g option for a process group, or -u for the processes belonging to a specific user.

The number of times the clock interrupts per second, and therefore the numbers of times the priority is recalculated, is defined by the HZ system variable. This is defined by default to be 100HZ, or 100 times a second. However, we are assuming that the priorities are only calculated once a second instead of 100 times.