您的位置:首页 > 运维架构 > Linux

linux进程task_struct结构体中的state域

2018-01-12 14:02 435 查看
(一)


task_struct是Linux内核的一种数据结构,它用task_struct结构体来描述进程的信息。下面来剖析一下进程中保存的主要的信息有哪些?

struct task_struct {

//进程的运行时状态
volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
void *stack;
atomic_t usage;

//进程当前的状态
/*
0x00000002表示进程正在被创建;

0x00000004表示进程正准备退出;

0x00000040 表示此进程被fork出,但是并没有执行exec;

0x00000400表示此进程由于其他进程发送相关信号而被杀死 。
*/
unsigned int flags;     /* per process flags, defined below */

unsigned int ptrace;
int on_rq;

//表示此进程的运行优先级,prio表示动态优先级,根据static_prio和交互性奖罚算出,static_prio是进程的静态优先级,在进程创建时确定,范围从-20到1
4000
9,越小优先级越高。
int prio, static_prio, normal_prio;

//进程的运行优先级
unsigned int rt_priority;

//list_head结构体
struct list_head tasks;

//mm_struct结构体,描述了进程内存的相关情况
struct mm_struct *mm, *active_mm;

/* per-thread vma caching */
u32 vmacache_seqnum;
struct vm_area_struct *vmacache[VMACACHE_SIZE];

/* task state */
//进程的状态参数
int exit_state;
int exit_code, exit_signal;

//父进程退出后信号被发送
int pdeath_signal;  /*  The signal sent when the parent dies  */

/* scheduler bits, serialized by scheduler locks */
unsigned sched_reset_on_fork:1;
unsigned sched_contributes_to_load:1;
unsigned sched_migrated:1;
unsigned sched_remote_wakeup:1;
unsigned :0; /* force alignment to the next boundary */

/* unserialized, strictly 'current' */
unsigned in_execve:1; /* bit to tell LSMs we're in execve */
unsigned in_iowait:1;

struct restart_block restart_block;

//进程号
pid_t pid;
//进程组号
pid_t tgid;

//进程的亲身父亲
struct task_struct __rcu *real_parent; /* real parent process */
//进程的现在的父亲,可能为继父
struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */
//进程的孩子链表
struct list_head children;      /* list of my children */
//进程兄弟的链表
struct list_head sibling;       /* linkage in my parent's children list */
//主线程的进程描述符
struct task_struct *group_leader;       /* threadgroup leader */

/* PID/PID hash table linkage. */
struct pid_link pids[PIDTYPE_MAX];

//该进程的所有线程链表
struct list_head thread_group;
struct list_head thread_node;

//该进程使用cpu时间的信息,utime是在用户态下执行的时间,stime是在内核态下执行的时间。
cputime_t utime, stime;

cputime_t gtime;
struct prev_cputime prev_cputime;

//启动时间,,只是时间基准不一样
u64 start_time;         /* monotonic time in nsec */
u64 real_start_time;    /* boot based time in nsec */

struct task_cputime cputime_expires;

//list_head的CPU时间
struct list_head cpu_timers[3];

//保存进程名字的数组,一般数组大小为15位
char comm[TASK_COMM_LEN];

/* file system info */
//文件系统信息
struct nameidata *nameidata;

/* 文件系统信息计数*/
int link_count, total_link_count;

/* filesystem information */
//文件系统相关信息结构体
struct fs_struct *fs;

/* open file information */
//打开文件信息的结构体
struct files_struct *files;

/* namespaces */
struct nsproxy *nsproxy;

/* signal handlers */
//信号相关信息的句柄
struct signal_struct *signal;
struct sighand_struct *sighand;

struct callback_head *task_works;

struct audit_context *audit_context;

struct seccomp seccomp;

/* Thread group tracking */
u32 parent_exec_id;
u32 self_exec_id;

/* journalling filesystem info */
void *journal_info;

/* VM state */
struct reclaim_state *reclaim_state;

struct backing_dev_info *backing_dev_info;

struct io_context *io_context;

unsigned long ptrace_message;
siginfo_t *last_siginfo; /* For ptrace use.  */

/*
* time slack values; these are used to round up poll() and
* select() etc timeout values. These are in nanoseconds.
*/
//松弛时间值,用来记录select和poll的超时时间,单位为ns
u64 timer_slack_ns;
u64 default_timer_slack_ns;

/* CPU-specific state of this task */
//该进程在特定CPU下的状态
struct thread_struct thread;

};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163


今天我们只是简单的了解了一下进程的信息,往后会再详细讲解进程

-----------------------------------------------------------------------------

(二)

谈到task_struct结构体,可以说她是linux内核源码中最复杂的一个结构体了,成员之多,占用内存之大。

鉴于她的复杂,我们不能简单的亵渎,而是要深入“窥探”.

下面先介绍这些复杂成员中的一员,state域

struct task_struct {

    volatile long state;    /* -1
unrunnable, 0 runnable, >0 stopped */

    ......

};

根据《Understanding the linux kernel .third edit》中的介绍:state域能够取5个互为排斥的值(通俗一点就是这五个值任意两个不能一起使用,只能单独使用)。

#define TASK_RUNNING        0

#define TASK_INTERRUPTIBLE    1

#define TASK_UNINTERRUPTIBLE    2

#define TASK_STOPPED        4

#define TASK_TRACED        8

现在一个一个介绍                                                                 TASK_RUNNING : 这个状态是正在占有cpu或者处于就绪状态的进程才能拥有。一旦某一个进程她的state域的值等于TASK_RUNNING,那么这个进程要么是正在运行,要么就是已经就绪,正在等待cpu时间片的调度。

TASK_INTERRUPIBLE :进程因为等待一些条件而被挂起进(阻塞)而所处的状态。这些条件主要包括:硬中断、资源、一些信号……,一旦等待的条件成立,进程就会从该状态(阻塞)迅速转化成为就绪状态,也就是state域的值变为TASK_RUNNING。

TASK_UNINTERRUPIBLE :其实他和TASK_UNINTERRUPIBLE 大致相同,除了传递一个信号和中断所引起的效果不同。对于处于TASK_UNINTERRUPIBLE状态的进程,哪怕我们传递一个信号或者有一个外部中断都不能唤醒他们。只有它所等待的资源可用的时候,他才会被唤醒。这个标志很少用,但是并不代表没有任何用处,其实他的作用非常大,特别是对于驱动刺探相关的硬件过程很重要,这个刺探过程不能被一些其他的东西给中断,否则就会让进城进入不可预测的状态。

TASK_STOP :进程的执行被停止,当进程接收到SIGSTOP、SIGTTIN、SIGTSTP或者SIGTTOU信号之后就会进入该状态。

TASK_TRACED :进程执行被调试程序所停止,当一个进程被另外的进程所监视,每一个信号都会让进城进入该状态。

其实还有两个附加的进程状态既可以被添加到state域中,又可以被添加到exit_state域中。只有当进程终止的时候,才会达到这两种状态。 

#define EXIT_ZOMBIE        16

#define EXIT_DEAD        32

 

EXIT_ZOMBIE :进程已经终止,但是它的父进程还没有调用wait4或者waitpid函数来获得有关进程终止的有关信息,在调用这两个函数之前,内核不会丢弃包含死去进程的进程描述符的数据结构的,防止父进程某一个时候需要着一些信息。

EXIT_DEAD :进程被系统释放,因为父进程已经调用了以上所提到的函数。现在内核也就可以安全的删除该进程的一切相关无用的信息了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: