linux初始化代碼陷阱門初始化:
trap_init主要功能對異常陷阱程序做初始化,其實就是設置中斷描述符表(IDT:interrupt Description Table)。IDT和GDT差不多每個IDT都是由一個8個字節組成。最多0.11內核中支持256個描述符,對於第n個描述符獲取地址大概可以這樣計算 add(n) = add(IDT)+8*(n-1)得到。
一:IDT中存放着三種描述符:
中斷門,陷阱門,任務門。
中斷門的模型:
31 16 15 13 12 8 5 4 0
過程入口偏移31..16 p DPL 01110類型 000 |
段選擇符 過程入口偏移15…0 |
過程入口偏移31..16 p DPL 01111類型 000 |
段選擇符 過程入口偏移15…0 |
二:工作過程
響應一個異常或者中斷的向量會作爲IDT表索引,如果所以指向中斷門或陷阱門則處理器會使用與call類似的操作處理中斷或者異常過程。任務會進行任務切換操作。首先會根據中斷向量號找到對應描述符,根據描述符中的段選擇符找到GDT全局或者LDT局部描述符表中的段描述符,找段基地址屬性等,由段地址+對應中斷描述符中的偏移找到具體的處理代碼點執行處理。
中斷向量 |
選擇符 屬性 偏移量
|
段基址 屬性 限長 |
異常處理過程 |
三:具體初始化工作
void trap_init(void)包含有set_trap_gate陷阱門設置, set_system_gate系統陷阱門配置兩種陷阱門做配置。
陷阱門和系統陷阱門差別就是特權及前者爲0,後者爲3用戶態,後者用於單步調試,溢出出錯等處理。
gate_addr:是描述符地址其佔用的8個字節將被書寫進描述符內容,描述符內容在最前面所示。
Type:是描述符的類型中斷門是0x0E就是前面紅色裏面的東西
Dpl: 權限特權標誌,比如陷阱門是0,系統陷阱門是3在圖中有dpl表示的。
Addr:偏移地址,找到段後,需要使用這個地址來找到具體的地址。
#define _set_gate(gate_addr,type,dpl,addr) /
"__asm__ ("movw %%dx,%%ax/n/t" /
//edx放的是addr偏移,eax初始爲0x00080000上面意思是
//eax = eax&0xFFFF00+addr&0x00FFFF,0008是段描述符
"movw %0,%%dx/n/t" /
//%0中放着0x8000[P位]+(dpl<<13)+(type<<8))組成陷阱門屬性將被
//放入陷阱門描述符高32中的第16位
"movl %%eax,%1/n/t" /
//此刻eax中內容是描述符需要的第32位: 段選擇符+偏移15-0
"movl %%edx,%2" /
//此刻edx內容爲描述符需要的高32位: 偏移31-16+屬性
: /
: "i" ((short) (0x8000+(dpl<<13)+(type<<8))), / //%0
"o" (*((char *) (gate_addr))), / //%1
"o" (*(4+(char *) (gate_addr))), / //%2
"d" ((char *) (addr)),"a" (0x00080000)) //edx
後面的對於陷阱門設置主要改變參數調用_set_gate宏來實現沒有其他可以解釋的地方。
#define set_intr_gate(n,addr) /
_set_gate(&idt[n],14,0,addr)
//這裏就是type不同中斷門區別與陷阱門的地方
#define set_trap_gate(n,addr) /
_set_gate(&idt[n],15,0,addr)
//這裏就是權限不同陷阱門區別與系統陷阱門的地方
#define set_system_gate(n,addr) /
_set_gate(&idt[n],15,3,addr)