国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 操作系統 > 正文

中斷——中斷描述符表的定義和初始化(二) (基于3.16-rc4)

2024-06-28 13:25:07
字體:
來源:轉載
供稿:網友
中斷——中斷描述符表的定義和初始化(二) (基于3.16-rc4)

上篇博文對中斷描述符表(IDT)中異常和非屏蔽中斷部分的初始化做了說明,這篇文章將分析外部中斷部分的初始化。

在上篇博文中,可以看到,內核在setup_once匯編片段中,對中斷和異常部分做了初步的初始化,用early_idt_handlers函數的地址來初始化異常門描述符,用ignore_int函數地址來初始化剩下的中斷門描述符。接著,內核在trap_init函數中對IDT做了進一步的初始化,用有效的異常處理程序來初始化中斷向量號為0-31的描述符。細心的你應該可以發現,在這一步初始化過程中,僅僅對異常和非屏蔽中斷做了初始化(也就是中斷向量號前32個),并沒有對后256-32=224個中斷門描述符初始化,也就是說后244個中斷門描述符依然指向的是ignore_int這個無用的函數。下面將分析中斷門描述符的最終初始化。首先介紹下interrupt全局數組,該數組中裝有了所有的中斷處理程序,如下所示:(arch/x86/kernel/entrt_32.S)

 1 .section .init.rodata,"a" 2 ENTRY(interrupt) 3 .section .entry.text, "ax" 4     .p2align 5 5     .p2align CONFIG_X86_L1_CACHE_SHIFT 6 ENTRY(irq_entries_start) 7     RING0_INT_FRAME 8 vector=FIRST_EXTERNAL_VECTOR 9 .rept (NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/710     .balign 3211   .rept    712     .if vector < NR_VECTORS13       .if vector <> FIRST_EXTERNAL_VECTOR14     CFI_ADJUST_CFA_OFFSET -415       .endif16 1:    pushl_cfi $(~vector+0x80)    /* Note: always in signed byte range */17       .if ((vector-FIRST_EXTERNAL_VECTOR)%7) <> 618     jmp 2f19       .endif20       .PRevious21     .long 1b22       .section .entry.text, "ax"23 vector=vector+124     .endif25   .endr26 2:    jmp common_interrupt27 .endr28 END(irq_entries_start)29 30 .previous31 END(interrupt)32 .previous

這段代碼定義了一個interrupt全局數組,如果不懂ATT匯編的話,這段代碼看起來非常吃力。下面筆者粗略分析下這段代碼,第1行聲明了一個數據段,第2行給這個數據段起了個名字,叫做‘inerrupt’,第3行又聲明了一個代碼段,該代碼段被包在了前邊的數據段當中,從第6行可看出這個代碼段名字叫做‘irq_entries_start’。接著4-5行說明了代碼段對齊的方式,接下來第7行給vector進行賦值,vector=32,實際上,interrup這個數組中存放的全是外部中斷,沒有異常,異常初始化已經在trap_init函數中完成了,而外部中斷的向量號從32開始,所以vector賦值32。接下來在第9,11行大家可以看到出現了偽指令.rept,這個偽指令是循環的意思,你可以把它當成for循環去理解,指令后邊的數字是循環次數。這個偽指令實際上告訴編譯器要把后邊的內容在內存中復制若干次。第9行的(NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/7值為32,要求其后的內容被循環復制32次。因此第9行和第11行合起來,就相當于一個雙重for循環,總共循環32*7=224次,這剛好就是外部中斷向量號的數量,每執行一次內部循環,就將一個外部中斷處理程序放入了一個數組元素中。接著第20行出現了.previous偽指令。該指令的意思是返回到上一個段中,在這里就是要返回到interrupt數據段中,第21行,在interrupt數據段中定義了一個long型數據,值為標號1,標號1實際上就是第16行代碼的地址。接著第22行又回到了當前代碼段中,讓vector自加1,然后第25行進入內重循環的下一次循環。第26行,標號2的這個指令夾在了內外兩重循環之間,說明每執行7次內循環就要將jmp common_interrupt復制一次。然后第27行進入外重循環的下一次循環。總共執行32*7次循環后,這段代碼就結束了。通過使用.preivous偽指令,最終實際上就定義了兩個數組,一個是interrput數組,該數組的每個元素均為.long 1b(第21行),另外一個數組是irq_entries_start,該數組每個元素中放入了若干條匯編指令(16-18行,26行)。這就是.previous的用處,每在irq_entries_start數組中初始化完一個元素,立馬返回到interrupt數組中定義一個指向irq_entries_start數組中剛初始化過的元素的指針(.long 1b),作為interrupt數組的元素。最終interrput數組中存放了224個指針(每個中斷處理程序的地址),分別指向了irq_entries_start數組中的對應元素。irq_entries_start數組每個元素存放的是幾條匯編指令(這些匯編指令就是中斷處理程序的開頭公共部分)。而且,通過第26行,可以看到,irq_entries_start數組每個元素都包含jmp common_interrupt指令,跳入到一段公共的代碼中。

上邊的工作,內核只是把所有的外部中斷處理程序用兩個數組管理起來了,接下來,就要在IDT(中斷描述符表)中初始化所有外部中斷的門描述符。代碼如下:(arch/x86/kernel/irqinit.c)

 1 void __init native_init_IRQ(void) 2 { 3     int i; 4  5     /* Execute any quirks before the call gates are initialised: */ 6     x86_init.irqs.pre_vector_init(); 7  8     apic_intr_init(); 9 10     /*11      * Cover the whole vector space, no vector can escape12      * us. (some of these will be overridden and become13      * 'special' SMP interrupts)14      */15     i = FIRST_EXTERNAL_VECTOR;16     for_each_clear_bit_from(i, used_vectors, NR_VECTORS) {17         /* IA32_SYSCALL_VECTOR could be used in trap_init already. */18         set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);19     }20 21     if (!acpi_ioapic && !of_ioapic)22         setup_irq(2, &irq2);23 24 #ifdef CONFIG_X86_3225     irq_ctx_init(smp_processor_id());26 #endif27 }

從16-19行,可以看出,用interrupt數組中存放的所有中斷處理程序地址來初始化IDT的中斷門描述符。set_intr_gate函數上篇博文已經分析過來,這里不再分析。

至此,所有IDT中的異常和中斷門描述符就初始化完成了。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 安仁县| 罗平县| 通州市| 武安市| 云安县| 湛江市| 德安县| 开原市| 安康市| 昂仁县| 德庆县| 建德市| 巴南区| 陆丰市| 从江县| 泗洪县| 文登市| 博白县| 大渡口区| 尼勒克县| 渭源县| 手机| 阿合奇县| 金塔县| 宜州市| 清流县| 永济市| 乌兰浩特市| 资阳市| 宾阳县| 抚顺市| 炎陵县| 和田县| 仙游县| 安岳县| 太谷县| 法库县| 西和县| 油尖旺区| 霍州市| 武安市|