- 首先要说以下PCB(进程控制块)
进程控制块是操作系统核心的一种数据结构,主要用来表示进程的状态,它能够使程序成为一个能够独立运行的基本单位,并且可以并发执行的进程。也就是说,系统是根据PCB来对并发执行的进程进行控制和管理。PCB中通常存放着操作系统用于描述进程的情况和控制进程运行的全部信息。 - PCB中包含的信息有8大部分:
- 标识符:
- 状态:
- 优先级:
- 程序计数器:
- 内存指针:
- 上下文数据:
- I/O状态信息:
- 记账信息:
而我们要谈的task_struct实际上就是进程控制块PCB,PCB在内核中存储为结构体的结构体名就是task_struct。所以说task_struct就是PCB,它会被装载到RAM中并且包含着进程的信息,每个进程都把它的信息放在这个结构体中。
task_struct的详细地址和具体内容介绍可以参考我的另一篇博客内容
https://blog.csdn.net/qq_36791466/article/details/90212212
task_struct中的部分成员(由于代码太长,就展示这一部分,行数大家找的时候也可以用来参考:1257-1739)
task_struct结构体成员解析:
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped
-1表示不可运行状态,0表示可运行状态,大于零表示停止状态
这里的volatile的是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
因为进程的状态有很多种,所以state的取值也有很多种:
状态名 | 取值 | 含义 |
---|---|---|
TASK_RUNNING | 0 | 运行态 |
TASK_INTERRUPTIBLE | 1 | 可中断睡眠态 |
TASK_UNINTERRUPTIBLE | 2 | 不可中断睡眠态 |
TASK_STOPPED | 4 | 停止态 |
TASK_TRACED | 8 | 僵死态 |
EXIT_ZOMBIE | 16 | 僵尸态 |
EXIT_DEAD | 32 | 死亡态 |
pid_t pid; //进程标识符
pid_t tgid; //线程组pid标识符
unsigned int flags;// per process flags, defined below
表示当前进程的标志,用于内核识别当前进程的状态,flags可能的状态有:
状态 | 含义 |
---|---|
PF_FORKNOEXEC | 进程创建,没有执行 |
PF_SUPERPRIV | 超级用户特权 |
PF_DUMPCORE | 异常情况的抓取 |
PF_SIGNALED | 进程被信号杀死 |
PF_EXITING | 进程开始关闭 |
struct task_struct __rcu *real_parent; /* real parent process */
struct task_struct __rcu *parent; /* recipient of SIGCHLD, wait4() reports */
/* children/sibling forms the list of my natural children
*/
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 */
成员 | 描述 |
---|---|
real_parent | 指向当前操作系统执行进程的父进程,如果父进程不在,则指向pid为1的init进程 |
parent | 指向当前进程的父进程,当当前进程终止时,需要向它发送wait4()的信号 |
children | 位于链表的头部,链表的所有元素都是children的子进程 |
sibling | 位于链表的头部,用于把当前进程插入到兄弟链表中(进程的兄弟链表) |
grop_leader | 进程组的领头进程 |
unsigned int ptrace
/*
* ptraced is the list of tasks this task is using ptrace on.
* This includes both natural children and PTRACE_ATTACH targets.
* p->ptrace_entry is p's link on the p->parent->ptraced list.
*/
struct list_head ptraced;
struct list_head ptrace_entry;
ptrace提供了一种使父进程得以监视和控制其他进程的方式,他还能改变子进程中的寄存器和内核映像,因而可以实现断点调试和系统调用的跟踪。当它被设置为0时表示不需要追踪。
int prio, static_prio, normal_prio;
unsigned int rt_priority;
成员 | 描述 |
---|---|
prio | 用来保存动态优先级 |
static_prio | 用来保存静态优先级,可以调用nice系统直接来修改 |
rt_priority | 用来保存实时优先级,取值范围为0~99 |
normal_prio | 它的取值取决于竞态优先级和调度策略 |
32位Linux操作系统的虚拟地址空间范围为0~4G(2^32),Linux内核将这4G字节的空间分为两部分,将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF)供内核使用。将较低的3G字节(从虚拟地址0x00000000到0xBFFFFFFF)供各个进程使用。而这4个G的地址空间都是虚拟地址空间,通过页表映射到物理内存中。
虚拟地址空间的查看:
pmap -p PID号
struct mm_struct *mm, *active_mm;
#ifdef CONFIG_COMPAT_BRK
unsigned brk_randomized:1;
#endif
#if defined(SPLIT_RSS_COUNTING)
struct task_rss_stat rss_stat;
#endif
成员 | 描述 |
---|---|
mm | 进程所拥有的内存空间描述符,对于内核线程的mm为NULL |
active_mm | 指进程运行时所使用的进程描述符 |
rss_stat | 被用来记录缓冲信息 |
cputime_t utime, stime, utimescaled, stimescaled;
cputime_t gtime;
#ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
struct cputime prev_cputime;
#endif
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN
seqlock_t vtime_seqlock;
unsigned long long vtime_snap;
enum {
VTIME_SLEEPING = 0,
VTIME_USER,
VTIME_SYS,
} vtime_snap_whence;
#endif
unsigned long nvcsw, nivcsw; /* context switch counts */
struct timespec start_time; /* monotonic time */
struct timespec real_start_time; /* boot based time */
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
unsigned long min_flt, maj_flt;
struct task_cputime cputime_expires;
struct list_head cpu_timers[3];
成员 | 描述 |
---|---|
utime/stiom | 记录进程在用户态/内核态下所经过的节拍数 |
utimescaled/stimescaled | 记录进程在用户态/内核态的运行时间 |
gtime | 以节拍计数的虚拟机运行时间 |
prev_utime/prev_stime | 先前的运行时间 |
nvcsw/nivcsw | 自愿/非自愿上下文切换计数 |
start_time/real_start_time | 进程创建事件,real_start_time中包含了进程睡眠时间 |
cputime_expires | 统计进程或进程组被跟踪的处理器的时间 |
min_flt/maj_flt | 缺页统计 |