小公司研发总监,既当司令也当兵!
分类: LINUX
2016-02-17 20:02:26
原文地址:task_struct解析(一) 进程状态 作者:kenvifire
task_struct 是内核用来表示进程的,包含进程的所有信息,该结构体定义在incluce\linux\Sched.h里
首先介绍一下状态信息
volatile long state
这个字段存储的是进程当前的状态
=====================================
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
具体参见:http://www.cppblog.com/mzty/archive/2006/08/08/10959.html
=====================================
/*
* Task state bitmask. NOTE! These bits are also
* encoded in fs/proc/array.c: get_task_state().
*
* We have two separate sets of flags: task->state
* is about runnability, while task->exit_state are
* about the task exiting. Confusing, but this way
* modifying one set can't modify the other one by
* mistake.
*/
下面四种表示进程的状态
#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define __TASK_STOPPED 4
#define __TASK_TRACED 8
/* in tsk->exit_state */
#define EXIT_ZOMBIE 16
#define EXIT_DEAD 32
/* in tsk->state again */
#define TASK_DEAD 64
#define TASK_WAKEKILL 128
#define TASK_WAKING 256
#define TASK_STATE_MAX 512
操作状态的宏
/* Convenience macros for the sake of set_task_state */
#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
#define TASK_TRACED (TASK_WAKEKILL | __TASK_TRACED)
/* Convenience macros for the sake of wake_up */
#define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)
#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED)
/* get_task_state() */
#define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \
TASK_UNINTERRUPTIBLE | __TASK_STOPPED | \
__TASK_TRACED)
#define task_is_traced(task) ((task->state & __TASK_TRACED) != 0)
#define task_is_stopped(task) ((task->state & __TASK_STOPPED) != 0)
#define task_is_dead(task) ((task)->exit_state != 0)
#define task_is_stopped_or_traced(task) \
((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0)
#define task_contributes_to_load(task) \
((task->state & TASK_UNINTERRUPTIBLE) != 0 && \
(task->flags & PF_FREEZING) == 0)
#define __set_task_state(tsk, state_value) \
do { (tsk)->state = (state_value); } while (0)
==========================================================
这里do{...}while 的作用是防止在把宏用在if...else语句中时,会导致编译不通过。
具体跟过应用参见http://www.cnblogs.com/flying_bat/archive/2008/01/18/1044693.html
===========================================================
#define set_task_state(tsk, state_value) set_mb((tsk)->state, (state_value))
==================================================================
set_mb宏:
#define set_mb(var, value) do { var = value; mb(); } while (0)
mb()宏:
#define mb() asm volatile("mfence":::"memory")
mb()宏在不同的系统架构中时不同的,这里取的是x86的架构下的代码
mfence是内存边界的意思,这条指令的作用是在mfence指令前的读写操作当必须在mfence指令后的读写操作前完成。
在这里的作用是,保证var=value的操作在其后续指令之前完成,防止value值被后面的代码改写
具体内存边界相关内容参见http://www.cnitblog.com/yuhensong/archive/2007/07/31/30994.aspx
====================================================================
设置进程当前状态的宏
/*
* set_current_state() includes a barrier so that the write of current->state
* is correctly serialised wrt the caller's subsequent test of whether to
* actually sleep:
*
* set_current_state(TASK_UNINTERRUPTIBLE);
* if (do_i_need_to_sleep())
* schedule();
*
* If the caller does not need such serialisation then use __set_current_state()
*/
#define __set_current_state(state_value) \
do { current->state = (state_value); } while (0)
#define set_current_state(state_value) \
set_mb(current->state, (state_value))
====================================================================================
这里定义了两个宏:__set_current_state(state_value)和set_current_state(state_value)
前者不带内存屏障,后者是带内存屏障的,即是前者的指令是串行执行的,后者可能是乱序的
=====================================================================================