天天看點

linux程序描述符tss,linux對TSS(任務狀态描述符)的使用---Linux核心筆記

linux2.4之前的核心有程序最大數的限制,受限制的原因是,每一個程序都有自已的TSS和LDT,而TSS(任務描述符)和LDT(私有描述符)必須放在GDT中,GDT最大隻能存放8192個描述符,除掉系統用掉的12描述符之外,最大程序數=(8192-12)/2, 總共4090個程序。從Linux2.4以後,全部程序使用同一個TSS,準确的說是,每個CPU一個TSS,在同一個CPU上的程序使用同一個TSS。TSS的定義在asm-i386/processer.h中,定義如下:

extern struct tss_struct init_tss[NR_CPUS];

在start_kernel()->trap_init()->cpu_init()初始化并加載TSS:

void __init cpu_init (void){int nr = smp_processor_id();    //擷取目前cpu

struct tss_struct * t = &init_tss[nr]; //目前cpu使用的tss

t->esp0 = current->thread.esp0;            //把TSS中esp0更新為目前程序的esp0set_tss_desc(nr,t);gdt_table[__TSS(nr)].b &= 0xfffffdff;load_TR(nr);                                              //加載TSSload_LDT(&init_mm.context);                //加載LDT

}

我們知道,任務切換(硬切換)需要用到TSS來儲存全部寄存器(2.4以前使用jmp來實作切換),

中斷發生時也需要從TSS中讀取ring0的esp0,那麼,程序使用相同的TSS,任務切換怎麼辦?

其實2.4以後不再使用硬切換,而是使用軟切換,寄存器不再儲存在TSS中了,而是儲存在

task->thread中,隻用TSS的esp0和IO許可位圖,是以,在程序切換過程中,隻需要更新TSS中

的esp0、io bitmap,代碼在sched.c中:

schedule()->switch_to()->__switch_to(),

void fastcall __switch_to(struct task_struct *prev_p, struct task_struct *next_p){struct thread_struct *prev = &prev_p->thread,     *next = &next_p->thread;struct tss_struct *tss = init_tss + smp_processor_id(); //目前cpu的TSS

ttss->esp0 = next->esp0; //用下一個程序的esp0更新tss->esp0

//拷貝下一個程序的io_bitmap到tss->io_bitmap

if (prev->ioperm || next->ioperm) {   if (next->ioperm) {        memcpy(tss->io_bitmap, next->io_bitmap,     IO_BITMAP_BYTES);    tss->bitmap = IO_BITMAP_OFFSET;   } else        tss->bitmap = INVALID_IO_BITMAP_OFFSET;}}

====