Monday, April 2, 2012

SLEEP: There is more to it than meets the eye

Today, I learnt a new thing. We all remember from our OS class that a Process (referred to as 'task' in Linux) can be in 'Running', 'Ready', 'Blocked'/ 'Sleeping' state etc. etc. However, in Linux, the 'Blocked' state is really represented by two states: TASK_INTERRUPTIBLE & TASK_UNINTERRUPTIBLE.

Following are the five states defined for a process in linux kernel 0.01:
Source File: include/linux/sched.h

#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 3
#define TASK_STOPPED 4

TASK_INTERRUPTIBLE: As the name suggests, a task (process) in this state can be interrupted by a signal. Thus, a process in this state has two ways to be woken up from its slumber:
1- Event notification for the event for which this particular process went to sleep in the first place.
2- A signal interrupt came (say, SIGKILL, SIGTERM etc.), and the process returns from sleep after properly handling the signal through a signal handler.

TASK_UNINTERRUPTIBLE: As the name suggests again, a task in this state can't be interrupted; not even by the old faithful `kill -9 ` command. It so happens, that sometimes tasks are at such a point in their execution history that they are not expected to be ever interrupted by any signal and they wake up from sleep only on getting a notification for the event, for which they went to sleep. One reason to do this that I know of, is to avoid corruption of kernel data structures.
A typical example of a task in this state, is of a task that is waiting for IO to complete on an underlying hardware device. That is why, you can't kill a task waiting on completion of IO even by `kill -9`. Another example is of a task trying to access NFS mounted files. And if by chance, your NFS server is down, then you can pretty much expect the task to sleep infinitely.

References:

No comments:

Post a Comment