标签:
尽管每个进程都可以拥有属于自己的地址空间,但所有进程必须共享CPU寄存器。因此在,在恢复一个进程执行之前,内核必须确保每个寄存器装入了挂起进程时的值。而这些必须装入的寄存器中的数据就称为硬件上下文。
80X86体系结构:
包括一个特殊的段类型,叫任务状态段(TSS),作用是存放硬件上下文。段是x86的概念,在保护模式下,段选择符参与寻址,段选择符在段寄存器中,而tss段则在tr寄存器中。当进程切换的时候就将
intel的建议:
为每一个进程准备一个独立的tss段,进程切换的时候切换tr寄存器使之指向该进程对应的tss段,然后在任务切换时(比如涉及特权级切换的中断)使用该段保留所有的寄存器。
Linux设计:
Linux内核并没有遵从Itel的建议为每个进程设置一个TSS,而是为每个CPU设置了一个TSS,tr寄存器保存该段。
按照Intel的设计思路,进程切换的硬件上下文要保存在TSS中,这是可以的,因为每个进程都有TSS,然而Linux中每个CPU有一个TSS,所有进程共享一个TSS,那么切换进程时的硬件上下文保存在哪里呢?答案是进程描述符中。在linux中,进程描述符有一个thread_struct类型的字段thread,只要进程被切换出去,内核就把硬件上下文保存在这个结构里面,这个结构里面包含了大部分的CPU寄存器,但是不不包括eax、ebx等等这些通用寄存器,它们的值放在哪里呢?自然是内核栈中啦!进程切换只发生在内核态,执行切换之前,用户进程使用的所有寄存器保存在内核堆栈中,这也包括ss和esp这对寄存器。
小总结:
执行进程切换时,硬件上下文保存在两个地方:
那么现在有个问题,既然Linux既然使用thread_struct保存硬件上下文,为什么要为每个CPU设计一个TSS呢?
理由有二:
由于进程切换不更换TSS本身,也就是根本不更换TR的内容。这是因为,改变TSS中SS0和ESP0所化的开销比通过装入TR以更换一个TSS要小得多。因此,在Linux内核中,TSS并不是属于某个进程的资源,而是全局性的公共资源。在多处理机的情况下,尽管内核中确实有多个TSS,但是每个CPU仍旧只有一个TSS,并且使用init_tass数组表示多个TSS,如果有N个CPU,那么数组的长度是N。
上述理由说明了在Linux中TSS的作用。到目前为止还有2个问题没有阐述清楚,即进程切换的时候,Linux是如何更新tss的内容的?thread_struct结构体到底长什么样子?下面就来解答这些问题。
从本质上说,每个进程切换由两步组成:
参考文章:
http://blog.csdn.net/dog250/article/details/6203529
http://oss.org.cn/kernel-book/ch05/5.4.1.htm
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/getnextwindow/article/details/47777735