歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> x86體系下Linux中的任務切換與TSS

x86體系下Linux中的任務切換與TSS

日期:2017/2/28 16:20:06   编辑:Linux教程

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 }, \
}

Copyright © Linux教程網 All Rights Reserved