tss的作用举例:保存不同特权级别下任务所使用的寄存器,特别重要的是esp,因为比如中断后,涉及特权级切换时(一个任务切换),首先要切换栈,这个栈显然是内核栈,那么如何找到该栈的地址呢,这需要从tss段中得到,这样后续的执行才有所依托(在x86机器上,c语言的函数调用是通过栈实现的)。只要涉及地特权环到高特权环的任务切换,都需要找到高特权环对应的栈,因此需要esp2,esp1,esp0起码三个esp,然而Linux只使用esp0。tss是什么:tss是一个段,段是x86的概念,在保护模式下,段选择符参与寻址,段选择符在段寄存器中,而tss段则在tr寄存器中。intel的建议:为每一个进程准备一个独立的tss段,进程切换的时候切换tr寄存器使之指向该进程对应的tss段,然后在任务切换时(比如涉及特权级切换的中断)使用该段保留所有的寄存器。Linux的做法:1.Linux没有为每一个进程都准备一个tss段,而是每一个cpu使用一个tss段,tr寄存器保存该段。进程切换时,只更新唯一tss段中的esp0字段到新进程的内核栈。2.Linux的tss段中只使用esp0和iomap等字段,不用它来保存寄存器,在一个用户进程被中断进入ring0的时候,tss中取出esp0,然后切到esp0,其它的寄存器则保存在esp0指示的内核栈上而不保存在tss中。3.结果,Linux中每一个cpu只有一个tss段,tr寄存器永远指向它。符合x86处理器的使用规范,但不遵循intel的建议,这样的后果是开销更小了,因为不必切换tr寄存器了。Linux的实现:1.定义tss:
struct tss_struct init_tss[NR_CPUS] __cacheline_aligned = { [0 ... NR_CPUS-1] = INIT_TSS };(arch/i386/kernel/init_task.c)
INIT_TSS定义为:
#define INIT_TSS {
.esp0 = sizeof(init_stack) + (long)&init_stack,
.ss0 = __KERNEL_DS,
.esp1 = sizeof(init_tss[0]) + (long)&init_tss[0],
.ss1 = __KERNEL_CS,
.ldt = GDT_ENTRY_LDT,
.io_bitmap_base = INVALID_IO_BITMAP_OFFSET,
.io_bitmap = { [ 0 ... IO_BITMAP_LONGS] = ~0 },
}
Linux的64位操作系统对32位程序的兼容Linux启动原理之-initrd和Debian实例相关资讯 Linux教程
- Linux教程:如何在命令行中查看目 (07/28/2014 12:22:23)
- Linux 修改root密码 (11/03/2012 07:53:38)
- su - root 与su root的区别 (06/06/2012 00:39:40)
| - Linux进程间通信:消息队列 (01/28/2013 09:43:00)
- U盘安装Linux开机无法启动解决方法 (10/07/2012 08:55:52)
- Windows 7/Linux 同步时间 (05/15/2012 06:17:55)
|
本文评论 查看全部评论 (0)