大家都知道进程,可是知道linux是怎么管理其进程的吗?每一个进程都有一个进程描述符,具体是task_struct结构体存储相关的信息,在linux/sched.h文件里定义,那么我们先看看linux内核3.0版本的task_struct结构体的定义吧(删除了不必要的字段,只保留了重要的字段)。
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
|
struct
task_struct {
//这个是进程的运行时状态,-1代表不可运行,0代表可运行,>0代表已停止。
volatile
longstate;
/*
flags是进程当前的状态标志,具体的如:
0x00000002表示进程正在被创建;
0x00000004表示进程正准备退出;
0x00000040 表示此进程被fork出,但是并没有执行exec;
0x00000400表示此进程由于其他进程发送相关信号而被杀死 。
*/
unsigned intflags;
//表示此进程的运行优先级
unsigned intrt_priority;
//这里出现了list_head结构体,详情请参考
structlist_head tasks;
//这里出现了mm_struct 结构体,该结构体记录了进程内存使用的相关情况,详情请参考
structmm_struct *mm;
/* 接下来是进程的一些状态参数*/
int
exit_state;
int
exit_code,exit_signal;
//这个是进程号
pid_t pid;
//这个是进程组号
pid_t tgid;
//real_parent是该进程的”亲生父亲“,不管其是否被“寄养”。
structtask_struct *real_parent;
//parent是该进程现在的父进程,有可能是”继父“
structtask_struct *parent;
//这里children指的是该进程孩子的链表,可以得到所有孩子的进程描述符,但是需使用list_for_each和list_entry,list_entry其实直接使用了container_of,详情请参考
struct
list_headchildren;
//同理,sibling该进程兄弟的链表,也就是其父亲的所有孩子的链表。用法与children相似。
structlist_head sibling;
//这个是主线程的进程描述符,也许你会奇怪,为什么线程用进程描述符表示,因为linux并没有单独实现线程的相关结构体,只是用一个进程来代替线程,然后对其做一些特殊的处理。
structtask_struct *group_leader;
//这个是该进程所有线程的链表。
structlist_head thread_group;
//顾名思义,这个是该进程使用cpu时间的信息,utime是在用户态下执行的时间,stime是在内核态下执行的时间。
cputime_tutime, stime;
//下面的是启动的时间,只是时间基准不一样。
structtimespec start_time;
structtimespec real_start_time;
//comm是保存该进程名字的字符数组,长度最长为15,因为TASK_COMM_LEN为16。
charcomm[TASK_COMM_LEN];
/* 文件系统信息计数*/
intlink_count, total_link_count;
/*该进程在特定CPU下的状态*/
structthread_struct
thread
;
/* 文件系统相关信息结构体*/
structfs_struct *fs;
/* 打开的文件相关信息结构体*/
structfiles_struct *files;
/* 信号相关信息的句柄*/
structsignal_struct *
signal
;
structsighand_struct *sighand;
/*这些是松弛时间值,用来规定select()和poll()的超时时间,单位是纳秒nanoseconds */
unsigned longtimer_slack_ns;
unsigned longdefault_timer_slack_ns;
};
|
可以知道
task_struct是Linux内核的一种数据结构,它会被装载到RAM里并且包含着进程的信息。
每个进程都把它的信息放在 task_struct 这个数据结构里,task_struct包含了这些内容:
标示符 : 描述本进程的唯一标示符,用来区别其他进程。
状态 :任务状态,退出代码,退出信号等。
优先级 :相对于其他进程的优先级。
程序计数器:程序中即将被执行的下一条指令的地址。
内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
上下文数据:进程执行时处理器的寄存器中的数据。
I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
保存进程信息的数据结构叫做 task_struct,并且可以在 include/linux/sched.h 里找到它。
所有运行在系统里的进程都以 task_struct 链表的形式存在内核里。
进程的信息可以通过/proc系统文件夹查看。要获取PID为400的进程信息,你需要查看/
proc/400这个文件夹。大多数进程信息同样可以使用top和ps这些用户级工具来获取。
本文转自 七十七快 51CTO博客,原文链接:http://blog.51cto.com/10324228/1784976