Linux内核:task_struct数据结构简要分析

为了管理进程,OS必须对每个进程所作的事情进行清楚地描述,OS使用数据结构来代表处理不同的实体,这个数据结构就是通常所说的进程描述符和进程控制块PCB,在linux中,使用task_struct结构体,每个进程都会被分配一个该结构,包含了进程的所有信息。注:task_struct结构体被定义在中task_struct中有非常多的成员,这仅仅是其中的一部分,随着学习的不断深入,会接触和学习更多的结构体成员。
摘要由CSDN通过智能技术生成

前言

为了管理进程,OS必须对每个进程所作的事情进行清楚地描述,OS使用数据结构来代表处理不同的实体,这个数据结构就是通常所说的进程描述符和进程控制块PCB,在linux中,使用task_struct结构体,每个进程都会被分配一个该结构,包含了进程的所有信息。

注:task_struct结构体被定义在<include/linux/sched.h>中

结构体成员

进程状态:

volatile long state;
 //volatile确保本条指令不会因编译器的优化而省略,且要求每次直接读值
 预定义的状态值:
 /* 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

进程标识符:

pid_t pid;
	pid_t tgid;
每个进程都有自己的pid,每个线程都有自己的线程id(pthread_t类型),但这是在用户空间的层面,而在内核层面中,线程其实就是进程,所以为了更好区分这些概念,一般使用task来指代内核中的进程概念,依旧用进程来指定用户空间层面的进程。

那么在内核中,每个线程都是一个task,所以每个线程都有自己的一份task_struct,而且都有自己独特的pid,那么此时tgid是干什么的那?
答:是用来说明线程是属于哪一个进程的,一个进程就是一个线程组,所以每个进程的所有线程都有着相同的tgid。当程序开始运行的时候,只有一个主线程,这个主线程的tgid就是pid,而当该主线程创建其他线程的时候,就继承了主线程的tgid。

进程内核栈:

当进程通过系统调用陷入内核时,内核代码所使用的栈并不是用户空间中的栈,而是一个内核空间的栈,也就是进程内核栈,它用于支持系统调用中的函数调用和自动变量,还用于保存一些系统调用前的应用信息,如用户空间栈指针、系统调用参数。

每个进程在创建的时候都会得到一个内核栈空间,内核栈和进程的对应关系是通过2个结构体中的指针成员完成的,其中就有tas_struct:这里的stack指向栈底。

void *stack;
//通过alloc_thread_info函数分配它的内核栈,通过free_thread_info函数释放所分配的内核栈,具体函数在fork.c中

另外一个是thread_info位于<thread.h>中,保存了线程所需的特定处理器的信息, 也就是进程所依赖体系结构的信息,以及通用的task_struct的指针:

/*
 * low level task data that entry.S needs immediate access to.
 * __switch_to() assumes cpu_context follows immediately after cpu_domain.
 */
struct thread_info {
    unsigned long        flags;        /* low level flags */
    int            preempt_count;    /* 0 => preemptable, <0 => bug */
    mm_segment_t        addr_limit;    /* address limit */
    struct task_struct    *task;        /* main task structure */
    struct exec_domain    *exec_domain;    /* execution domain */
    __u32            cpu;        /* cpu */
    __u32            cpu_domain;    /* cpu domain 
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值