【Linux】task_struct结构体成员中字段介绍

引言

任何计算机系统都包含一个基本的程序集合,成为操作系统(OS)。操作系统包括:
(1)内核:进程管理、内存管理、文件管理、驱动管理……
(2)其他程序:函数库、shell程序……


那么计算机是如何管理进程的呢?

总结起来就是先把进程描述起来,用struct结构体,再把进程组织起来,用链表或者更高效的数据结构。


什么是进程呢?


概念

  • 课本内容:程序的一个执行实例,正在执行的程序等;
  • 内核观点:担当分配系统资源(CPU时间,内存)的实体;

描述进程的PCB

进程信息被放在一个叫做进程控制块的数据结构中,可理解为进程属性的集合,课本上叫做PCB(process control block),Linux操作系统下的PCB是:task_struct。

task_struct内容分类

  • 标识符:与进程相关的唯一标识符,用来区别正在执行的进程和其他进程。
  • 状态:描述进程的状态,因为进程有挂起,阻塞,运行等好几个状态,所以都有个标识符来记录进程的执行状态。
  • 优先级:如果有好几个进程正在执行,就涉及到进程被执行的先后顺序的问题,这和进程优先级这个标识符有关。
  • 程序计数器:程序中即将被执行的下一条指令的地址。
  • 内存指针:程序代码和进程相关数据的指针。
  • 上下文数据:进程执行时处理器的寄存器中的数据。
  • I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表等。
  • 记账信息:包括处理器的时间总和,记账号等等。
  • 其他信息

每一个PCB都包含这些信息,它定义在下图文件的sched.h中。
这里写图片描述


下面让我们来看一下sched.h中对task_struct的结构体成员们:

进程状态

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

上面这个变量就是描述进程状态的成员,其中volatile关键字是降低编译器对代码的优化,使得state变量一直从变量的内存中读取内容而不是寄存器;从而保证对操作系统状态实时访问的稳定性。
state成员的可能取值如下:

/*
  * 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_DEAD               16
 #define EXIT_ZOMBIE             32
 #define EXIT_TRACE              (EXIT_ZOMBIE | EXIT_DEAD)

/* in tsk->state again */
 #define TASK_DEAD               64
 #define TASK_WAKEKILL           128    /** wake on signals that are deadly **/
 #define TASK_WAKING             256
 #define TASK_PARKED             512
 #define TASK_NOLOAD             1024
 #define TASK_STATE_MAX          2048

 /* 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)

由上面定义可知道:变量内容<0是不运行的,=0是运行状态,>0是停止状态。
下面介绍几个常用的取值:

状态 描述
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;    //线程组标识符

进程标记符

unsigned int flags; /* per process flags, defined below */ 

flags反应进程的状态信息,用于内核识别当前进程的状态。
它的取值范围如下:

/*
* Per process flags
*/
#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_FSTRANS      0x00020000      /* inside a filesystem transaction */
#define PF_KSWAPD       0x00040000      /* I am kswapd */
#define PF_MEMALLOC_NOIO 0x00080000     /* Allocating memory without IO involved */
#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 表示进程开始关闭

进程调度

int prio, static_prio, normal_prio;
unsigned int rt_priority;
成员 描述
static_prio 用来保存静态优先级,可以调用nice系统直接来修改取值范围为100~139
rt_priority 用来保存实时优先级,取值范围为0~99
prio 用来保存动态优先级
normal_prio 它的值取决于静态优先级和调度策略

实时优先级和静态优先级的取值范围中,值越大,优先级越低。

你可能感兴趣的:(Linux)