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 it, 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, 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. Note that only root can increase a process’s 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.

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.

Finding Block Size of filesystem

To find the block size used by a filesystem, try the following command:

# /sbin/tune2fs -l /dev/hda1

tune2fs 1.27 (8-Mar-2002)
Filesystem volume name: /boot
Last mounted on:
Filesystem UUID: 124f3bd6-cb9a-4b3f-88bd-82ff128890dc
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal filetype needs_recovery sparse_super
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 26104
Block count: 104391
Reserved block count: 5219
Free blocks: 91710
Free inodes: 26063
First block: 1
Block size: 1024
Fragment size: 1024
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 2008
Inode blocks per group: 251
Last mount time: Thu May 15 13:23:05 2003
Last write time: Thu May 15 13:23:05 2003
Mount count: 8
Maximum mount count: -1
Last checked: Mon Mar 3 18:36:23 2003
Check interval: 0 ()
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Journal UUID:
Journal inode: 8
Journal device: 0x0000
First orphan inode: 0