进程管理2---进程描述符及任务结构

(一)进程描述符及任务结构

内核把进程的列表存放在叫任务队列双向循环链表中。链表中的每一项都是task_struct(进程描述符或进程控制块)

每个进程在内核中都有一个进程控制块(PCB)存放进程的管理和控制信息,在32位机器上他大约有1.7KB。

   task_struct包含以下内容:

(1)PID:又称进程标识符,每个进程都会被分配一个唯一的数字编号,用来区别其他进程,

ID为0调度进程(交换进程)1init进程,2页守护进程,
(2)状态:任务状态,退出代码,退出信号等。 
(3)优先级:相对于其他进程的优先级。 
(4)程序计数器:程序中即将被执行的下一条指令的地址。 
(5)内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。 
(6)上下文数据:进程执行时处理器的寄存器中的数据。 
(7)I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和正在被进程使用的文件列表。 
(8)记账信息:可能包括处理器时间总和,使用的时钟总数,时间限制,记账号等。

                                      进程管理2---进程描述符及任务结构_第1张图片

(二)分配进程描述符

Linux通过slab分配器分配进程描述符,2.6以前的内核中,各个进程的task_struct存放在它们内核栈尾端,因为寄存器较少,只要通过栈指针就能计算出它的位置。现在都是动态生成task_struct,所以只需要在栈底或栈顶(内核栈的尾端)创建一个新的结构struct thread_info.

                                 进程管理2---进程描述符及任务结构_第2张图片

                                            进程管理2---进程描述符及任务结构_第3张图片

(三)进程描述符的存放

内核通过一个唯一的进程标识值或PID来标识每一个进程。PID是一个数,表示为pid_t隐含类型,实际上就是int类型。PID最大值为3268。

在内核访问任务(进程)通常需要获取指向其task_struct的指针。通过current宏查找当前正在运行进程的进程描述符 ,不同硬件体系结构该宏的实现也不同,有的是拿一个寄存器,有的只能在内核栈尾端创建thread_info结构,通过计算偏移间接的查找task_struct结构。在x86系统上,current把栈指针的后13个有效为屏蔽掉啊,用来计算出thread_info的偏移。该操作通过current_thread_info()函数来完成。

(四)进程状态

进程描述符state存放进程的状态,系统中所有的进程都会处于该状态的一种。

                    进程管理2---进程描述符及任务结构_第4张图片

这里所说的运行状态就是我们平常所理解的运行态和就绪态。

可中断和不可中断是阻塞状态的两种。

                       进程管理2---进程描述符及任务结构_第5张图片

(五)设置当前进程状态

内核经常需要调整某个进程状态。这时最好使用set_task_state(task,state)函数(将任务task的状态设置为state)

该函数将指定的进程设置为指定的状态。必要的时候回设置内存屏障来强制其他处理器做重新排序。否则,它等价与:task->state = state;

(五)程序上下文

可执行程序是进程的重要组成部分。这些代码从一个可执行文件载入到进程地址空间执行。一般就是用户空间。当一个程序执行系统调用或触发异常,就陷入了内核空间。此时成内核“代表进程执行”并处于进程上下文中。除非有优先级更高的进程需要执行并由调度器做出相应调整,否则在内核退出时,程序恢复在用户空间会继续执行。

系统调用和异常处理程序是对内核明确定义的接口。进程只有通过这些接口才能陷入内核执行——对内核的所有访问都必须通过这些接口。

(六)进程家族树

所有进程都是PID为1的init进程的后代。内核在系统启动的最后阶段启动init进程。该进程读取系统的初始化脚本并执行其他相关程序,最终完成系统启动整个过程。

拥有同一个父进程的所有进程称为兄弟。进程间的关系存放在进程描述符中。每个task_struct都包含一个指向其父进程task_struct、叫parent的指针。还包含一个称为children的子进程链表。

你可能感兴趣的:(进程管理2---进程描述符及任务结构)