在介绍task_struct,我们要先来看几个概念
一:进程的概念
1. 从用户角度来看:进程是程序的一次动态执行过程
2.从内核角度看:
3.那PCB结构中的数据有哪些呢
4.在进程执行的任意时刻,都可由如下元素来表征
- 标识符:与进程相关的唯一标识符,用来区别正在执行的进程和其他进程。
- 状态:描述进程的状态,因为进程有挂起,阻塞,运行等好几个状态,所以都有个标识符来记录进程的执行状态。
- 优先级:如果有好几个进程正在执行,就涉及到进程被执行的先后顺序的问题,这和进程优先级这个标识符有关。
- 程序计数器:程序中即将被执行的下一条指令的地址。
- 内存指针:程序代码和进程相关数据的指针。
- 上下文数据:进程执行时处理器的寄存器中的数据。
- I / O状态信息:包括显示的I / O请求,分配给进程的I / O设备和被进程使用的文件列表等。
- 记账信息:包括处理器的时间总和,记账号等等
5.进程标识符
6.进程创建的一般过程
二:进程模型
1.两状态模型
在任何时刻,一个进程要么正在执行,要么未执行,因而可以构建最简单的模型
2.五状态模型
(1)运行态:进程正在执行。
(2)就绪态:进程做好了准备,只要有机会就开始执行。
(3)阻塞态:进程在某些事情发生前不能执行
(4)新建态:刚刚创建的进程
(5)退出态:操作系统从可执行进程组中释放出的进程
3.经典Linux七态
三.task_struct的源码成员解析
task_struct头文件sched.h链接https://elixir.bootlin.com/linux/latest/source/include/linux/sched.h
(1)进程状态
/* -1 unrunnable, 0 runnable, >0 stopped: */
volatile longstate;
上面这个变量就是描述进程状态的成员,结合Ç语言我们学到的知识挥发性关键字是降低编译器对代码的优化,是状态变量一直从变量的内存中读取内容而不是寄存器;从而保证对操作系统状态实时访问的稳定性。
(2)成员的可能取值如下
/* * 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. */ /* Used in tsk->state: */ #define TASK_RUNNING 0x0000 #define TASK_INTERRUPTIBLE 0x0001 #define TASK_UNINTERRUPTIBLE 0x0002 #define __TASK_STOPPED 0x0004 #define __TASK_TRACED 0x0008 /* Used in tsk->exit_state: */ #define EXIT_DEAD 0x0010 #define EXIT_ZOMBIE 0x0020 #define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD) /* Used in tsk->state again: */ #define TASK_PARKED 0x0040 #define TASK_DEAD 0x0080 #define TASK_WAKEKILL 0x0100 #define TASK_WAKING 0x0200 #define TASK_NOLOAD 0x0400 #define TASK_NEW 0x0800 #define TASK_STATE_MAX 0x1000我们可以看到变量定义后面的注释,它说明变量内容<0是不运行的,=0是运行状态,>0是停止状态。
(3)
状态 | 描述 |
---|---|
TASK_RUNNING | 表示进程正在执行或者处于准备执行的状态 |
TASK_INTERRUPTIBLE | 进程因为等待某些条件处于阻塞(挂起的状态),一旦等待的条件成立,进程便会从该状态转化成就绪状态 |
TASK_UNINTERRUPTIBLE | 意思与TASK_INTERRUPTIBLE类似,但是我们传递任意信号等不能唤醒他们,只有它所等待的资源可用的时候,他才会被唤醒。 |
TASK_STOPPED | 进程被停止执行 |
TASK_TRACED | 进程被debugger等进程所监视。 |
EXIT_ZOMBIE | 进程的执行被终止,但是其父进程还没有使用wait()等系统调用来获知它的终止信息,此时进程成为僵尸进程 |
EXIT_DEAD | 进程被杀死,即进程的最终状态。 |
TASK_KILLABLE | 当进程处于这种可以终止的新睡眠状态中,它的运行原理类似于 TASK_UNINTERRUPTIBLE,只不过可以响应致命信号 |
pid_t pid;//进程的标识符
pid_t tgid;//线程组标识符//进程标识符就不用解释了,它的引入是为了区别每个进程;
tgid的引入是由于Unix程序员希望同一组线程具有相同的pid所以就引入了tgid.
(5)进程标记符
unsignedint flags; /* per process flags, defined below */
flags反应进程的状态信息,用于内核识别当前进程的状态。
取值范围如下:
/* * Per process flags */ #define PF_IDLE 0x00000002 /* I am an IDLE thread */ #define PF_EXITING 0x00000004 /* Getting shut down */ #define PF_EXITPIDONE 0x00000008 /* PI exit done on shut down */ #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ #define PF_WQ_WORKER 0x00000020 /* I'm a workqueue worker */ #define PF_FORKNOEXEC 0x00000040 /* Forked but didn't exec */ #define PF_MCE_PROCESS 0x00000080 /* Process policy on mce errors */ #define PF_SUPERPRIV 0x00000100 /* Used super-user privileges */ #define PF_DUMPCORE 0x00000200 /* Dumped core */ #define PF_SIGNALED 0x00000400 /* Killed by a signal */ #define PF_MEMALLOC 0x00000800 /* Allocating memory */ #define PF_NPROC_EXCEEDED 0x00001000 /* set_user() noticed that RLIMIT_NPROC was exceeded */ #define PF_USED_MATH 0x00002000 /* If unset the fpu must be initialized before use */ #define PF_USED_ASYNC 0x00004000 /* Used async_schedule*(), used by module init */ #define PF_NOFREEZE 0x00008000 /* This thread should not be frozen */ #define PF_FROZEN 0x00010000 /* Frozen for system suspend */ #define PF_KSWAPD 0x00020000 /* I am kswapd */ #define PF_MEMALLOC_NOFS 0x00040000 /* All allocation requests will inherit GFP_NOFS */ #define PF_MEMALLOC_NOIO 0x00080000 /* All allocation requests will inherit GFP_NOIO */ #define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */ #define PF_KTHREAD 0x00200000 /* I am a kernel thread */ #define PF_RANDOMIZE 0x00400000 /* Randomize virtual address space */ #define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */ #define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_allowed */ #define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */ #define PF_MUTEX_TESTER 0x20000000 /* Thread belongs to the rt mutex tester */ #define PF_FREEZER_SKIP 0x40000000 /* Freezer should not count it as freezable */ #define PF_SUSPEND_TASK 0x80000000 /* This thread called freeze_processes() and should not be frozen */
常用状态
状态 | 描述 |
---|---|
PF_FORKNOEXEC | 表示进程刚被创建,但还没有执行 |
PF_SUPERPRIV | 表示进程拥有超级用户特权 |
PF_SIGNALED | 表示进程被信号杀出 |
PF_EXITING | 表示进程开始关闭 |
(6)表示进程亲属关系的成员
成员 | 描述 |
---|---|
real_parent | 指向当前操作系统执行进程的父进程,如果父进程不存在,指向pid为1的init进程 |
paren | 指向当前进程的父进程,当当前进程终止时,需要向它发送wait4()的信号 |
children | 位于链表的头部,链表的所有元素都是children的子进程 |
group_leader | 指向进程组的领头进程 |
int prio, static_prio, normal_prio;
unsigned int rt_priority;
成员 | 描述 |
---|---|
static_prio | 用来保存静态优先级,可以调用nice系统直接来修改取值范围为100~139 |
rt_priority | 用来保存实时优先级,取值范围为0~99 |
prio | 用来保存动态优先级 |
normal_prio | 它的值取决于静态优先级和调度策略 |
(9)进程地址空间
成员 | 描述 |
---|---|
mm | 进程所拥有的内存空间描述符,对于内核线程的mm为NULL |
active_mm | 指进程运行时所使用的进程描述符 |
rss_stat | 被用来记录缓冲信息 |