Wednesday, August 21, 2013

Linux -- D state processes & TASK_KILLABLE state

The following figure show the process state transition:

D state is a special sleep mode..
In D state , the code can not be interrupted..
When the process in D state, actually It seems blocked from our perspective, but actually nothing is blocked inside the kernel.
For example, when a process issues an I/O operation , the kernel is triggered to run the relevant system call..
This code goes from filename to filesystem, from filesystem to block device and device driver, and then device driver sends the command to the hardware to fetch a block on disk.
The process, on the other hand ; is put in sleeping state (D). When the data is fetched, the process is put in runnable state again. After this point, the process will run(continue its work) when the scheduler allow it to.
D state processes,  can not be killed with kill signals..
The exact name for the D state is TASK_UNINTERRUPTABLE, and as mentioned in its name, the processes in this state can not be interrupted..
In the most cases, this unkillable processes appear when NFS shares are used for the IO. This is probably because the error detection in local disks are very fast when you compare it with the TCP timeout (300 seconds approx.)

The new task_killable state introduced in Linux 2.6.25 is a solution to kill these kind of unkillable processes.
Task_killable works just like the Task_interruptable + it can respond to fatal signals..

The functions for the TASK_KILLABLE state is below;
Reference: Ibm

  • int wait_event_killable(wait_queue_t queue, condition); 
    This function is defined in include/linux/wait.h; it puts the calling process to sleep killably in queue until the conditionevaluates to true.
  • long schedule_timeout_killable(signed long timeout); 
    This is defined in kernel/timer.c; this routine basically sets the current task's state to TASK_KILLABLE and callsschedule_timeout(), which makes the calling task sleep for timeout number of jiffies. (In UNIX systems, a jiffy is basically the time between two consecutive clock ticks.)
  • int wait_for_completion_killable(struct completion *comp); 
    Defined in kernel/sched.c, this routine is used to wait killably for the completion of an event. This function callsschedule_timeout() for MAX_SCHEDULE_TIMEOUT (defined to be equal to LONG_MAX) jiffies if there are no fatal signals pending.
  • int mutex_lock_killable(struct mutex *lock); 
    Defined in kernel/mutex.c, this routine is used to acquire mutex lock. However, if the lock is not available and the task is waiting to get the lock, and in the meantime it gets a fatal signal, the task would be removed from the list of waiters waiting for the mutex lock to process the signal.
  • int down_killable(struct semaphore *sem); 
    Defined in kernel/semaphore.c, it is used to acquire the semaphore sem. If the semaphore is not available, it's put to sleep; if a fatal signal is delivered to it, it would be removed from the waiters' list and would have to respond to the signal. The other two methods of acquiring a semaphore are by using the routines down() or down_interruptible(). The function down() is deprecated now; you should use either down_killable() or down_interruptible().

No comments :

Post a Comment