浅析task_struct结构体

本文详细介绍了进程的概念,强调进程是程序的一次动态执行过程,并深入剖析了Linux系统中进程控制块task_struct的结构,包括进程状态、唯一标识、内核栈、亲属关系、调度信息、时间数据成员等关键内容。
摘要由CSDN通过智能技术生成

本文内容概述:
1.进程的概念
2.进程控制块
3.剖析Linux下的PCB—task_struct


说到task_struct,或许你是非常陌生的。如果我说他其实就是Linux下的对进程控制块PCB定义的一个结构体,你或许就会懂那么一点。下边开始今天分享的主题:

1.进程的概念:

说到进程控制块PCB,不得不说一下进程。在之前的操作系统的课程学习中,给出的定义:进程是程序的一次动态的执行过程。(这样,你真的是能想明白吗?概念确实是比较抽象的,反正之前学习的时候我不是很清楚的)。进程=程序段+数据段+进程控制块。当我再次学习操作系统学习进程的时候,却有了更深层次的认识:


从操作系统的层次:进程是程序的一个执行实例;进程是正在执行的程序;进程是能分配处理机并且由处理机执行的实体。这么一说,没有正在执行的程序就一定不是进程吗?不是。假如在单处理机的系统中,一次只能执行一个进程(也就是说,一次只能有一个进程处于运行状态),那么其他的被加载到内存的程序(已经获得了除处理机之外的所需的全部资源),也是进程。
从内核的层次:担当分配系统资源(包括内存等)的实体。
进程的两个基本元素是程序代码(有可能被其他进程所共享)和与代码相关联的数据集。其实这里,与“进程=程序段+数据段+进程控制块 ”是一样的。数据集就是指的是数据段和进程控制块。


2.进程控制块:

为了描述进程的信息,我们引入了进程控制块这个数据结构。那么,为什么需要进程控制块呢?它起着什么作用?
在单处理机系统,我们每次只能执行一个进程,我们如何知道是哪个进程在执行?执行完这个进程之后,又需要去执行哪些进程?假如一个进程由于种种原因,需要被中断(不是被杀死),那么之后再来执行此进程的时候,我们怎么会知道之前执行到哪(不可能从头开始执行),等等情形,所以就需要进程控制块。
通过分析以上的种种情况,我们得出:进程控制块至少应该包含进程标识(是进程的唯一标识,PID),还有进程的优先级,记录进程的上下文信息,记录进程下一次下一条指令的地址,进程中的程序的地址,等等(下文将会给出task_struct结构体的成员)。
当操作系统要调度某进程去执行时,要从该进程的PCB中查询进程的优先级和现行状态;
当系统调度到某个进程时,要根据PCB中保存的现行信息先去回复现场,然后再去修改进程的状态,根据程序的地址,找到程序的位置,并开始执行;
当进程由于某个原因需要暂停时,就必须将现行状态保存在PCB中,并记录下一条指令的地址。
可见,在进程的整个执行过程中,进程控制块都起着非常重要的作用。下边我们就来剖析Linux下的PCB—task_struct结构体。


3.剖析Linux下的PCB—task_struct

关于task_struct的定义, 位于/usr/include/linux/sched.h文件(centos6.5下)中。
下边我就结构体中的数据成员进行分类:


(1)进程的状态:
一个进程是执行状态还是睡眠状态还是阻塞状态,将在下边的成员中进行描述。
volatile long state;
state的可能取值为:

#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_ZOMBIE     16 //僵尸状态的进程,表示进程被终止,但是父进程还没       有获取它的终止信息,比如进程有没有执行完等信息。                     
#define EXIT_DEAD       32 //进程的最终状态,进程死亡。
/* in tsk->state again */ 
#define TASK_DEAD       64 //死亡
#define TASK_WAKEKILL       128 //唤醒并杀死的进程
#define TASK_WAKING     256 //唤醒进程 

(2)进程的唯一标识

 pid_t pid;//进程的唯一标识
 pid_t tgid;// 线程组的领头线程的pid成员的值

pid是进程的唯一表示,范围是0~32767,可以表示32768个进程。
在Linux系统中,一个线程组的所有线程使用和该线程组的领头线程相同的PID,并被存放在tgid成员中。(线程是程序运行的最小单位,进程是程序运行的基本单位。)


(3)进程的内核栈

 void *stack;//用来维护进程的内核栈。

Linux内核是通过以下的结构体来表示进程的内核栈:

union thread_union {
    struct thread_info thread_info;
    unsigned long stack[THREAD_SIZE/sizeof(long)];
};

注明:关于内核栈,之后再来补充。


(4)进程的标记:

unsigned int flags; 

//进程的标志信息
#
  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值