Chinaunix首页 | 论坛 | 博客
  • 博客访问: 657958
  • 博文数量: 185
  • 博客积分: 1875
  • 博客等级: 上尉
  • 技术积分: 2107
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-23 23:21
个人简介

有时候,就是想窥视一下不知道的东东,因为好奇!

文章分类

全部博文(185)

文章存档

2024年(1)

2023年(3)

2020年(1)

2019年(1)

2018年(1)

2017年(2)

2016年(69)

2015年(53)

2014年(14)

2013年(1)

2012年(5)

2011年(25)

2010年(9)

分类: LINUX

2016-09-08 23:03:30

内核资料收集

        内核能挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行。这种行为称为进程切换,任务切换或上下文切换。
    1. 硬件上下文
            每个进程拥有属于自己的地址空间,所有进程共享CPU寄存器。恢复一个进程的执行之前,内核必须确保每个寄存器装入
        了挂起进程时的值。
      进程恢复执行前,必须装入寄存器的一组数据称为硬件上下文。硬件上下文是进程可执行上下文的一个子集。80x86体系
        结构的linux中,进程硬件上下文的一部分存放在TSS段,剩余部分存放在内核态堆栈中。
            用prev变量表示切换出的进程的描述符,next表示切换进的进程的描述符。则进程切换就可以定义成这样的行为:保存prev
        硬件上下文,用next硬件上下文代替prev。因为进程切换经常发生,因此减少保存和装入硬件上下文所花费的时间非常重要。
            早期linux版本利用80x86体系结构所提供的硬件支持,通过far jmp指令跳到next进程TSS描述符的选择符来执行进程切换。
        执行这条指令时,CPU通过自动保存原来的硬件上下文,装入新的硬件上下文来执行硬件上下文切换。
            基于以下两点原因,linux2.6使用软件执行进程切换:
                a. 通过mov指令逐步执行切换,可以较好控制所装入数据的合法性。尤其是可以检查ds和es段寄存器的值成为可能,这
                    些值可能被恶意伪造。用单独的far jmp指令时,不能进行此检查。
                b. 两种方法所需时间大致相同。当前的切换代码还可改进,却不能对硬件上下文切换进程优化。
            进程切换只发生在内核态。在执行进程切换前,用户态进程使用的所有寄存器内容都已保存在内核态堆栈上,包括ss和esp
        等寄存器的内容。
    2. 任务状态段(TSS)
            80x86体系结构包括了一个特殊的段类型,叫任务状态段(Task State Segment, TSS)来存放硬件上下文。尽管Linux并不使用
        硬件上下文切换,但强制它为系统中每个不同的CPU创建一个TSS。这样做的主要理由:
                a. 当80x86的CPU从用户态切换到内核态时,它从TSS中获取内核态堆栈地址。
                b. 用户态进程通过in/out指令访问一个i/o端口时,CPU需要访问存放在TSS中的i/o许可权位图,以检查该进程是否有访问
                     端口的权限。
            tss_struct结构描述TSS的格式。init_tss为每个不同的CPU存放一个TSS。每次进程切换时,内核都更新TSS的某些字段以便相
        应的CPU控制单元可以安全的检索到它需要的信息。因此,TSS反映了CPU上的当前进程的特权级,但不必为没在运行的进程保
        留TSS。
            在intel的原始设计中,系统的每个进程都应该有自己的TSS。linux设计中,每个CPU只有一个TSS
               ......
    3. thread字段
         进程切换时,被替换的进程的硬件上下文必须保存在别处。不能像intel原始设计的那样保存在TSS段,因为Linux为每个CPU而不
     是进程使用TSS。因此每个进程描述符包含一个类型为thread_struct的thread字段。
          进程切换出去,内核就将硬件上下文保存在thread结构字段。
     4. 执行进程切换
          进程切换可能只发生在精心定义的点:schedule()函数。
          本质上,进程切换由两步组成:
               a. 切换页全局目录,以安装一个新的地址空间
               b. 切换内核态堆栈和硬件上下文,因为硬件上下文提供了内核执行新进程所需要的所有信息,包含CPU信息。
     4.1. switch_to宏
              进程切换时,内核态堆栈和硬件上下文的切换由switch_to宏执行。
              原型:switch_to(prev, next, last)
                   三个参数中,prev/next分别表示,被替换进程和新进程描述符地址在内存中的位置。last是输出参数,记录上一个进程的
            描述符地址。至于为什么要用三个参数,需要仔细消化。内核代码中用法如下:
                        switch_to(prev, next, prev)
     4.2. 保存和加载FPU/MMX/XMM寄存器
          ......
阅读(540) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~