在linux内核中进程以及线程(多线程也是通过一组轻量级进程实现的)都是通过task_struct结构体来描述的,我们称它为进程描述符。而thread_info则是一个与进程描述符相关的小数据结构,它同进程的内核态栈stack存放在一个单独为进程分配的内存区域。由于这个内存区域同时保存了thread_info和stack,所以使用了联合体来定义,相关数据结构如下(基于4.4.87版本内核):
 thread_union联合体定义:
union thread_union {
struct thread_info thread_info;
unsigned long stack[THREAD_SIZE/sizeof(long)];
};

thread_info结构体定义:

struct thread_info {
unsigned long flags; /* low level flags */
mm_segment_t addr_limit; /* address limit */
struct task_struct *task; /* main task structure */
int preempt_count; /* 0 => preemptable, <0 => bug */
int cpu; /* cpu */
};
task_struct的结构比较复杂,只列出部分成员变量,完整的可以在下面这个网站直接查看对应版本的内核代码
struct task_struct {
volatile long state;
void *stack;
 //...
#ifdef CONFIG_SMP
int on_cpu;
int wake_cpu;
#endif
int on_rq;
 //...
#ifdef CONFIG_SCHED_INFO
struct sched_info sched_info;
#endif
 //...
pid_t pid;
pid_t tgid;
 //...
}; 
用一副图来表示:
 
这样设计的好处就是,得到stack,thread_info或task_struct任意一个数据结构的地址,就可以很快得到另外两个数据的地址。
我们可以通过crash工具在ubuntu系统上做个实验,来窥视一下某个进程的进程描述符
如果通过crash分析内核数据结构,可参考:
这里以进程systemd进程为例,其pid=1
crash> task
PID: TASK: ffff88007c898000 CPU: COMMAND: "systemd"
struct task_struct {
state = ,
stack = 0xffff88007c894000,
usage = {
counter =
},
。。。
可以看到systemd进程的task_struct结构体指针task=0xffff88007c898000
通过task->stack这个结构体成员即可定位到进程的内核栈地址 stack=0xffff88007c894000
另外从之前的图可以看到,thread_info和stack处于同一地址空间,且thread_info在这段地址空间的最低地址处,而且这个地址空间是以THREAD_SIZE对齐的,所以只要将stack地址的最低N位变为0,即可得到thread_info的地址(2^N=THREAD_SIZE)
例如当THREAD_SZIE=8K时,systemd的thread_info地址就等于0xffff88007c894000&(~(0x1FFF)) = 0xffff88007c894000
crash> * thread_info 0xffff88007c894000
struct thread_info {
task = 0xffff88007c898000,
flags = ,
status = ,
cpu = ,
addr_limit = {
seg =
},
sig_on_uaccess_error = ,
uaccess_err =
}
 
  而通过thread_info->task这个成员变量,又能访问到进程的task_struct结构体,这样就形成了task_struct, thread_info,stack三者之间的关系网,知道其中任何一个,都可以快速的访问到另外两个,提高了数据存取的效率。
 
 

linux内核中task_struct与thread_info及stack三者的关系的更多相关文章

  1. Linux内核中的中断栈与内核栈的补充说明【转】

    转自:http://blog.chinaunix.net/uid-12461657-id-3487463.html 原文地址:Linux内核中的中断栈与内核栈的补充说明 作者:MagicBoy2010 ...

  2. Linux内核中的fastcall和asmlinkage宏

    代码中看见:#define _fastcall 所以了解下fastcall -------------------------------------------------------------- ...

  3. Apparmor——Linux内核中的强制访问控制系统

      AppArmor 因为最近在研究OJ(oline judge)后台的安全模块的实现,所以一直在研究Linux下沙箱的东西,同时发现了Apparmor可以提供访问控制. AppArmor(Appli ...

  4. Linux内核中的软中断、tasklet和工作队列具体解释

    [TOC] 本文基于Linux2.6.32内核版本号. 引言 软中断.tasklet和工作队列并非Linux内核中一直存在的机制,而是由更早版本号的内核中的"下半部"(bottom ...

  5. (笔记)Linux内核中内存相关的操作函数

    linux内核中内存相关的操作函数 1.kmalloc()/kfree() static __always_inline void *kmalloc(size_t size, gfp_t flags) ...

  6. 进程在Linux内核中的角色扮演

    在Linux内核中,内核将进程.线程和内核线程一视同仁,即内核使用唯一的数据结构task_struct来分别表示他们:内核使用相同的调度算法对这三者进行调度:并且内核也使用同一个函数do_fork() ...

  7. Linux内核中namespace之PID namespace

    前面看了LInux PCI设备初始化,看得有点晕,就转手整理下之前写的笔记,同时休息一下!!~(@^_^@)~ 这片文章是之前写的,其中参考了某些大牛们的博客!! PID框架的设计 一个框架的设计会考 ...

  8. Linux 内核中的 Device Mapper 机制

    本文结合具体代码对 Linux 内核中的 device mapper 映射机制进行了介绍.Device mapper 是 Linux 2.6 内核中提供的一种从逻辑设备到物理设备的映射框架机制,在该机 ...

  9. 向linux内核中添加外部中断驱动模块

    本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...

随机推荐

  1. sublime上配置markdown

    等等等等 简书一个不错的教程:Sublime Text3的Markdown配置 补充说明:第一步可以直接找 Tools-->install package control. ^.^ ...

  2. niosii dma实验中的一点感想

    1,使用nios给出的驱动函数的顺序一般为1,清中断2,写控制寄存器,3,写参数寄存器4,中断注册,5,开始工作.因为开始工作控制位在控制寄存器中,所以会想到到最后一块写,省事,但是在dma试验中发现 ...

  3. 不得不注意tornado多进程部署的副作用

    tornado多进程启动时,采用的是fork的方式. 一个现有进程可以调用fork函数创建一个新进程.由fork创建的新进程被称为子进程(child process).fork函数被调用一次但返回两次 ...

  4. JAVA框架--hibernate、struts2、spring

    JAVAEE——spring01:介绍.搭建.概念.配置详解.属性注入和应用到项目   JAVAEE——struts2_04:自定义拦截器.struts2标签.登陆功能和校验登陆拦截器的实现   JA ...

  5. Oracle 13c OEM 安装手册

    1       安装准备工作 以下包已Redhat 为准,其他版的操作系统以官方手册为准. 1.1         Oracle Management Service 依赖如下包 glibc-comm ...

  6. (转)Android开发--常用的传感器总结

    随着手机的发展,现在各大手机支持的传感器类型也越来越多,在开发中利用传感器进行某些操作令人们有一种耳目一新的感觉,例如微信中的摇一摇,以及手机音乐播放器中的摇一摇切歌.今天来简单介绍下Android中 ...

  7. Python学习之异常处理

    1.首先了解错误和异常的概念: 错误:代码运行前的代码错误或者是程序执行过程中的逻辑错误 1:语法错误:代码不符合解释器或者编译器语法(代码错误) 2:逻辑错误:不完整或者不合法输入或者计算出现问题( ...

  8. 转 : 配置 mysql-advanced-5.6.21-winx64 免安装版

    mySQL包:mysql-advanced-5.6.21-winx64.zip 下载地址:https://edelivery.oracle.com/EPD/Search/handle_go 服务器版本 ...

  9. simple_one_for_one 和 one_for_one的区别

    参考这里http://blog.sina.com.cn/s/blog_77cb45a70102v1ja.html 用起来最直观的不同点 simple_one_for_one需要手工start_chil ...

  10. erlang使用心跳模式启动shell

    资料http://blog.yufeng.info/archives/2832 借鉴自从http://blog.csdn.net/mycwq/article/details/18306753 测试例子 ...