成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

運維 系統運維
本篇文章主要是向大家介紹了x86體系下Linux中的任務切換與TSS的相關知識,作者通過程序實例進行講解,相信看后大家對Linux系統會理解的更加深刻。

本篇文章主要是向大家介紹了x86體系下Linux中的任務切換TSS的相關知識,作者通過程序實例進行講解,相信看后大家對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定義為:

  1. #define INIT_TSS  {                              
  2. .esp0        = sizeof(init_stack) + (long)&init_stack,      
  3. .ss0        = __KERNEL_DS,                      
  4. .esp1        = sizeof(init_tss[0]) + (long)&init_tss[0],      
  5. .ss1        = __KERNEL_CS,                      
  6. .ldt        = GDT_ENTRY_LDT,                  
  7. .io_bitmap_base    = INVALID_IO_BITMAP_OFFSET,              
  8. .io_bitmap    = { [ 0 ... IO_BITMAP_LONGS] = ~0 },          

2.初始化tss:

  1. struct tss_struct * t = init_tss + cpu;  
  2. ...  
  3. load_esp0(t, thread);  
  4. set_tss_desc(cpu,t);  
  5. cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;  
  6. load_TR_desc();  

相關函數或者宏為:

  1. #define load_TR_desc() __asm__ __volatile__("ltr %%ax"::"a" (GDT_ENTRY_TSS*8))  
  2. static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)  
  3. {  
  4. _set_tssldt_desc(&cpu_gdt_table[cpu][entry], (int)addr,  
  5. offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);  
  6. }  
  7. #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr) 

經過上述的初始化,tr永遠指向唯一的tss段,然而tss段中的esp0以及iomap卻是不斷隨著進程切換而變化的。
3.進程切換時切換全局唯一tss段中的esp0以及iomap即可:
在__switch_to中:

  1. struct tss_struct *tss = init_tss + cpu;  
  2. ...  
  3. load_esp0(tss, next); 

從而改變了tss的esp0。
此時如果進程在用戶態被中斷,機器切到ring0,從tr中取出唯一的tss段,找到它的esp0,將堆棧切過去即可,然后把所有的其它寄存器都保存在tss當前的esp0指示的內核也就是ring0的堆棧上。

責任編輯:馮宇 來源: Linux社區
相關推薦

2011-12-19 10:55:58

云計算中國電信

2021-08-16 13:26:49

Linuxx86 Linux

2011-05-16 15:31:51

英特爾x86關鍵任務

2010-12-09 14:22:08

2011-12-01 11:09:48

AMDx86服務器英特爾

2009-06-18 09:11:03

微軟Windows 7下載

2011-12-14 13:02:05

Power虛擬機X86平臺服務器

2010-04-02 09:15:20

服務器

2023-02-22 09:53:55

架構芯片

2021-07-07 11:35:17

Linux內存段尋址

2021-06-07 15:20:22

Linux X861MB內存BIOS

2012-09-19 09:51:45

Windows Serx86服務器選型

2011-06-23 08:33:58

大型機x86服務器

2015-05-12 17:16:05

戴爾云計算

2011-02-20 22:23:43

X86虛擬化XenServer

2011-11-10 09:26:48

Solaris 11

2009-08-28 14:38:33

2020-09-23 12:42:08

Linux

2010-04-15 13:44:45

x86服務器微軟WinServer

2011-04-08 09:52:34

WindowsX86ARM
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩av一区二区在线观看 | 欧美日韩手机在线观看 | 在线观看黄色电影 | 亚洲h在线观看 | 精品1区| 天天干天天玩天天操 | 欧美综合国产精品久久丁香 | 亚洲一区二区三区在线免费 | 黄色在线播放视频 | 羞羞视频网 | 欧美精品1区2区 | 色综合久久天天综合网 | 91超碰caoporn97人人 | 暴草美女 | 国产精品久久久久久久久图文区 | 成人片免费看 | 特黄毛片 | 国产精品1区2区 | 久久综合一区 | 国产色网站 | 老司机深夜福利网站 | 亚洲免费高清 | 97国产爽爽爽久久久 | 无毛av | 国产激情视频在线观看 | www国产亚洲精品久久网站 | 亚洲成人免费在线观看 | 精品国产伦一区二区三区观看方式 | 国产精品久久久久久238 | 天天人人精品 | 免费视频二区 | 欧美亚洲激情 | 国产在线中文字幕 | 91精品一区二区三区久久久久 | 97视频免费 | 在线视频 亚洲 | 一区二区三区高清 | 国产精品视频中文字幕 | av色站 | 久久99精品久久久久久国产越南 | 国产精品久久久久久久免费大片 |