Linux操作系統(tǒng)分析_第1頁
Linux操作系統(tǒng)分析_第2頁
Linux操作系統(tǒng)分析_第3頁
Linux操作系統(tǒng)分析_第4頁
已閱讀5頁,還剩91頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Linux操作系統(tǒng)分析主講:陳香蘭助教:賈永泉、毛熠璐xlanchen@3606864-83(西區(qū)電三421)Autumn2007xlanchen@2007.9.271LinuxOperatingSystemAnalysis上次課進(jìn)程的創(chuàng)建進(jìn)程調(diào)度xlanchen@2007.9.272LinuxOperatingSystemAnalysis中斷和異常xlanchen@2007.9.27xlanchen@2007.9.273LinuxOperatingSystemAnalysis為什么會(huì)有中斷內(nèi)核的一個(gè)主要功能就是處理硬件處理器速度一般比外設(shè)快很多內(nèi)核必須處理其他任務(wù),只有當(dāng)外設(shè)真正完成了準(zhǔn)備好了時(shí)CPU才轉(zhuǎn)過來處理外設(shè)也可以用輪詢的方式來處理,但顯然效率不高中斷機(jī)制就是滿足上述條件的一種解決辦法xlanchen@2007.9.274LinuxOperatingSystemAnalysis主要內(nèi)容中斷信號(hào)的作用和中斷信號(hào)處理的一般原則I/O設(shè)備如何引起CPU中斷x86CPU如何在硬件級(jí)處理中斷信號(hào)Linux內(nèi)核中軟件級(jí)中斷處理及其數(shù)據(jù)結(jié)構(gòu)xlanchen@2007.9.275LinuxOperatingSystemAnalysis中斷和異常中斷(廣義)會(huì)改變處理器執(zhí)行指令的順序,通常與CPU芯片內(nèi)部或外部硬件電路產(chǎn)生的電信號(hào)相對(duì)應(yīng)中斷——異步的:

由硬件隨機(jī)產(chǎn)生,在程序執(zhí)行的任何時(shí)候可能出現(xiàn)異?!降模?/p>

在(特殊的或出錯(cuò)的)指令執(zhí)行時(shí)由CPU控制單元產(chǎn)生我們用“中斷信號(hào)”來通稱這兩種類型的中斷xlanchen@2007.9.276LinuxOperatingSystemAnalysis中斷信號(hào)的作用中斷信號(hào)提供了一種特殊的方式,使得CPU轉(zhuǎn)去運(yùn)行正常程序之外的代碼比如一個(gè)外設(shè)采集到一些數(shù)據(jù),發(fā)出一個(gè)中斷信號(hào),CPU必須立刻響應(yīng)這個(gè)信號(hào),否則數(shù)據(jù)可能丟失當(dāng)一個(gè)中斷信號(hào)到達(dá)時(shí),CPU必須停止它當(dāng)前正在做的事,并且切換到一個(gè)新的活動(dòng)為了做到這這一點(diǎn),在進(jìn)程的內(nèi)核態(tài)堆棧保存程序計(jì)數(shù)器的當(dāng)前值(即eip和cs寄存器),并把與中斷信號(hào)相關(guān)的一個(gè)地址放入進(jìn)程序計(jì)數(shù)器xlanchen@2007.9.277LinuxOperatingSystemAnalysis中斷信號(hào)的處理原則快!當(dāng)內(nèi)核正在做一些別的事情的時(shí)候,中斷會(huì)隨時(shí)到來。無辜的正在運(yùn)行的代碼被打斷中斷處理程序在run的時(shí)候可能禁止了同級(jí)中斷中斷處理程序?qū)τ布僮?,一般硬件?duì)時(shí)間也是非常敏感的內(nèi)核的目標(biāo)就是讓中斷盡可能快的處理完,盡其所能把更多的處理向后推遲上半部分(topbottom)和下半部分(halfbottom)xlanchen@2007.9.278LinuxOperatingSystemAnalysis允許不同類型中斷的嵌套發(fā)生,這樣能使更多的I/O設(shè)備處于忙狀態(tài)盡管內(nèi)核在處理一個(gè)中斷時(shí)可以接受一個(gè)新的中斷,但在內(nèi)核代碼中還在存在一些臨界區(qū),在臨界區(qū)中,中斷必須被禁止xlanchen@2007.9.279LinuxOperatingSystemAnalysis中斷上下文中斷上下文不同于進(jìn)程上下文中斷或異常處理程序執(zhí)行的代碼不是一個(gè)進(jìn)程它是一個(gè)內(nèi)核控制路徑,代表了中斷發(fā)生時(shí)正在運(yùn)行的進(jìn)程執(zhí)行作為一個(gè)進(jìn)程的內(nèi)核控制路徑,中斷處理程序比一個(gè)進(jìn)程要“輕”(中斷上下文只包含了很有限的幾個(gè)寄存器,建立和終止這個(gè)上下文所需要的時(shí)間很少)xlanchen@2007.9.2710LinuxOperatingSystemAnalysis中斷上下文舉例分析A,B,C,D在互相搶占上的關(guān)系 假設(shè): 2個(gè)interruptcontext,記為A和B 2個(gè)process,記為C和D1,假設(shè)某個(gè)時(shí)刻C占用CPU運(yùn)行,此時(shí)A中斷發(fā)生,C被A搶占,A得以在CPU上執(zhí)行。 由于Linux不為中斷處理程序設(shè)置processcontext,A只能使用C的kernelstack作為自己的運(yùn)行棧xlanchen@2007.9.2711LinuxOperatingSystemAnalysis2,無論如何,Linux的interruptcontextA絕對(duì)不會(huì)被某個(gè)進(jìn)程C或者D搶占?。?這是由于所有已經(jīng)啟動(dòng)的interruptcontexts,不管是interruptcontexts之間切換,還是在某個(gè)interruptcontext中執(zhí)行代碼的過程,決不可能插入scheduler調(diào)度例程的調(diào)用。 除非interruptcontext主動(dòng)或者被動(dòng)阻塞進(jìn)入睡眠,喚起scheduler,但這是必須避免的,危險(xiǎn)性見第3點(diǎn)說明。xlanchen@2007.9.2712LinuxOperatingSystemAnalysis3,關(guān)于第2點(diǎn)的解釋:首先,interruptcontext沒有processcontext,如果被某個(gè)進(jìn)程搶占之后就沒法恢復(fù)到原來的interruptcontext下了,這即損害了A的利益也污染了C的kernelstack。 其次,如果interruptcontextA由于阻塞或是其他原因睡眠,外界對(duì)系統(tǒng)的響應(yīng)能力將變得不可忍受xlanchen@2007.9.2713LinuxOperatingSystemAnalysis4,那么interruptcontextA和B的關(guān)系又如何呢? 由于可能在interruptcontext的某個(gè)步驟打開了CPU的IFflag標(biāo)志,這使得在A過程中,B的irqline已經(jīng)觸發(fā)了PIC,進(jìn)而觸發(fā)了CPUIRQpin,使得CPU執(zhí)行中斷B的interruptcontext,這是中斷上下文的嵌套過程。5,通常Linux不對(duì)不同的interruptcontexts設(shè)置優(yōu)先級(jí),這種任意的嵌套是允許的 當(dāng)然可能某個(gè)實(shí)時(shí)Linux的patch會(huì)不允許低優(yōu)先級(jí)的interruptcontext搶占高優(yōu)先級(jí)的interruptcontextxlanchen@2007.9.2714LinuxOperatingSystemAnalysis中斷和異常的分類(Intel文檔)中斷分為:可屏蔽中斷(Maskableinterrupt)I/O設(shè)備發(fā)出的所有中斷請(qǐng)求(IRQ)都可以產(chǎn)生可屏蔽中斷??善帘沃袛嗫梢蕴幱趦煞N狀態(tài):屏蔽的(masked)和非屏蔽的(unmasked)非屏蔽中斷(Nonmaskableinterrupt)只有幾個(gè)特定的危急事件才引起非屏蔽中斷。如硬件故障或是掉電xlanchen@2007.9.2715LinuxOperatingSystemAnalysis異常分為:處理器探測(cè)異常由CPU執(zhí)行指令時(shí)探測(cè)到一個(gè)反常條件時(shí)產(chǎn)生,如溢出、除0錯(cuò)等編程異常由編程者發(fā)出的特定請(qǐng)求產(chǎn)生,通常由int類指令觸發(fā)通常叫做“軟中斷”例如系統(tǒng)調(diào)用xlanchen@2007.9.2716LinuxOperatingSystemAnalysis對(duì)于處理器探測(cè)異常,根據(jù)異常時(shí)保存在內(nèi)核堆棧中的eip的值可以進(jìn)一步分為:故障(fault):eip=引起故障的指令的地址通??梢约m正,處理完異常時(shí),該指令被重新執(zhí)行例如缺頁異常陷阱(trap):eip=隨后要執(zhí)行的指令的地址。異常中止(abort):eip=???發(fā)生嚴(yán)重的錯(cuò)誤。eip值無效,只有強(qiáng)制終止受影響的進(jìn)程xlanchen@2007.9.2717LinuxOperatingSystemAnalysis中斷向量每個(gè)中斷和異常由0~255之間的一個(gè)數(shù)(8位)來標(biāo)識(shí),Intel稱其為中斷向量。非屏蔽中斷的向量和異常的向量是固定的可屏蔽中斷的向量可以通過對(duì)中斷控制器的編程來改變xlanchen@2007.9.2718LinuxOperatingSystemAnalysis中斷的產(chǎn)生每個(gè)能夠發(fā)出中斷請(qǐng)求的硬件設(shè)備控制器都有一條稱為IRQ(Interrupt

ReQuest)的輸出線。所有的IRQ線都與一個(gè)中斷控制器的輸入引腳相連中斷控制器與CPU的INTR引腳相連設(shè)備設(shè)備控制器中斷控制器IRQCPUINTRxlanchen@2007.9.2719LinuxOperatingSystemAnalysis中斷控制器執(zhí)行下列動(dòng)作:1,監(jiān)視IRQ線,對(duì)引發(fā)信號(hào)檢查2,如果一個(gè)引發(fā)信號(hào)出現(xiàn)在IRQ線上a,把此信號(hào)轉(zhuǎn)換成對(duì)應(yīng)的中斷向量b,把這個(gè)向量存放在中斷控制器的一個(gè)I/O端口,從而允許CPU通過數(shù)據(jù)總線讀這個(gè)向量c,把引發(fā)信號(hào)發(fā)送到處理器的INTR引腳,即產(chǎn)生一個(gè)中斷d,等待,直到CPU應(yīng)答這個(gè)信號(hào);收到應(yīng)答后,清INTR引腳3,返回到第一步xlanchen@2007.9.2720LinuxOperatingSystemAnalysisIRQ號(hào)和中斷向量號(hào)中斷控制器對(duì)輸入的IRQ線從0開始順序編號(hào)IRQ0,IRQ1,…Intel給中斷控制器分配的中斷向量號(hào)從32開始,上述IRQ線對(duì)應(yīng)的中斷向量依次是32+0、32+1、…可以對(duì)中斷控制器編程:修改起始中斷向量的值,或有選擇的屏蔽/激活每條IRQ線屏蔽≠丟失xlanchen@2007.9.2721LinuxOperatingSystemAnalysis屏蔽的中斷不會(huì)丟失一旦被激活,中斷控制器又會(huì)將它們發(fā)送到CPU有選擇的屏蔽/激活I(lǐng)RQ線

≠全局屏蔽/激活前者通過對(duì)中斷控制器編程實(shí)現(xiàn)后者通過特定的指令操作CPU中的狀態(tài)字xlanchen@2007.9.2722LinuxOperatingSystemAnalysisI386:開中斷和關(guān)中斷CPU可以將屏蔽所有的可屏蔽終端Eflags中的IF標(biāo)志:

0=關(guān)中斷;

1=開中斷。關(guān)中斷時(shí),CPU不響應(yīng)中斷控制器發(fā)布的任何中斷請(qǐng)求內(nèi)核中使用cli和sti指令分別清除和設(shè)置該標(biāo)志xlanchen@2007.9.2723LinuxOperatingSystemAnalysis傳統(tǒng)的中斷控制器:8259A傳統(tǒng)的中斷控制器使用兩片8259A以“級(jí)聯(lián)”的方式連接在一起每個(gè)芯片可以處理最多8個(gè)不同的IRQ線主從兩片8259A的連接:從主的IRQ2引腳因此,一共可以處理最多15個(gè)不同的IRQ線xlanchen@2007.9.2724LinuxOperatingSystemAnalysis8259A:設(shè)置起始中斷向量號(hào)xlanchen@2007.9.2725LinuxOperatingSystemAnalysis8259A:禁止/激活某個(gè)IRQ線取變量的第x個(gè)字節(jié)xlanchen@2007.9.2726LinuxOperatingSystemAnalysis異常X86處理器發(fā)布了大約20種不同的異常。某些異常通過硬件出錯(cuò)碼說明跟異常相關(guān)的信息內(nèi)核為每個(gè)異常提供了一個(gè)專門的異常處理程序xlanchen@2007.9.2727LinuxOperatingSystemAnalysis故障非屏蔽中斷陷阱,斷點(diǎn)調(diào)試陷阱故障,缺頁異常中止異常處理程序異常處理程序發(fā)出的信號(hào)xlanchen@2007.9.2728LinuxOperatingSystemAnalysis中斷描述符表(InterruptDescriptorTable,IDT)中斷描述符表是一個(gè)系統(tǒng)表,它與每一個(gè)中斷或者異常向量相聯(lián)系每個(gè)向量在表中有相應(yīng)的中斷或者異常處理程序的入口地址。每個(gè)描述符8個(gè)字節(jié),共256項(xiàng),占用空間2KB內(nèi)核在允許中斷發(fā)生前,必須適當(dāng)?shù)某跏蓟疘DTCPU的idtr寄存器指向IDT表的物理基地址lidt指令xlanchen@2007.9.2729LinuxOperatingSystemAnalysisIDT包含3種類型的描述符任務(wù)門:Linux沒有使用任務(wù)門中斷門:指定中斷處理程序,進(jìn)入中斷門時(shí),系統(tǒng)進(jìn)入關(guān)中斷狀態(tài)陷阱門:與中斷門類似,但進(jìn)入陷阱門時(shí),系統(tǒng)不會(huì)進(jìn)入關(guān)中斷狀態(tài)xlanchen@2007.9.2730LinuxOperatingSystemAnalysis中斷和異常的硬件處理

進(jìn)入中斷/異常假定:內(nèi)核已經(jīng)初始化,CPU在保護(hù)模式下運(yùn)行CPU的正常運(yùn)行:當(dāng)執(zhí)行了一條指令后,cs和eip這對(duì)寄存器包含了下一條將要執(zhí)行的指令的邏輯地址。在執(zhí)行這條指令之前,CPU控制單元會(huì)檢查在運(yùn)行前一條指令時(shí)是否發(fā)生了一個(gè)中斷或者異常。如果發(fā)生了一個(gè)中斷或異常,那么CPU控制單元執(zhí)行下列操作:xlanchen@2007.9.2731LinuxOperatingSystemAnalysis1,確定與中斷或者異常關(guān)聯(lián)的向量i(0~255)2,讀idtr寄存器指向的IDT表中的第i項(xiàng)3,從gdtr寄存器獲得GDT的基地址,并在GDT中查找,以讀取IDT表項(xiàng)中的段選擇符所標(biāo)識(shí)的段描述符。4,確定中斷是由授權(quán)的發(fā)生源發(fā)出的。中斷:中斷處理程序的特權(quán)不能低于引起中斷的程序的特權(quán)(對(duì)應(yīng)GDT表項(xiàng)中的DPLvsCS寄存器中的CPL)編程異常:還需比較CPL與對(duì)應(yīng)IDT表項(xiàng)中的DPL這個(gè)描述符指定中斷或異常處理程序所在段的基地址只允許從低特權(quán)級(jí)“陷入”到高特權(quán)級(jí),反之不可以禁止低特權(quán)級(jí)用戶訪問特殊的門xlanchen@2007.9.2732LinuxOperatingSystemAnalysis5,檢查是否發(fā)生了特權(quán)級(jí)的變化,一般指是否由用戶態(tài)陷入了內(nèi)核態(tài)。

如果是由用戶態(tài)陷入了內(nèi)核態(tài),控制單元必須開始使用與新的特權(quán)級(jí)相關(guān)的堆棧a,讀tr寄存器,訪問運(yùn)行進(jìn)程的tss段b,用與新特權(quán)級(jí)相關(guān)的棧段和棧指針裝載ss和esp寄存器。這些值可以在進(jìn)程的tss段中找到c,在新的棧中保存ss和esp以前的值,這些值指明了與舊特權(quán)級(jí)相關(guān)的棧的邏輯地址xlanchen@2007.9.2733LinuxOperatingSystemAnalysis6,若發(fā)生的是故障,用引起異常的指令地址修改cs和eip寄存器的值,以使得這條指令在異常處理結(jié)束后能被再次執(zhí)行7,在棧中保存eflags、cs和eip的內(nèi)容8,如果異常產(chǎn)生一個(gè)硬件出錯(cuò)碼,則將它保存在棧中9,裝載cs和eip寄存器,其值分別是IDT表中第i項(xiàng)門描述符的段選擇符和偏移量字段。這對(duì)寄存器值給出中斷或者異常處理程序的第一條指定的邏輯地址xlanchen@2007.9.2734LinuxOperatingSystemAnalysis此時(shí)的進(jìn)程內(nèi)核態(tài)堆棧(注意此進(jìn)程可以是任意一個(gè)進(jìn)程,中斷處理程序不關(guān)心這個(gè))ssespeflagscseip8KBunionesp進(jìn)程描述符用戶態(tài)進(jìn)程上下文和前次中斷保存ss,esp,eflags,cs和eipeflagscseip進(jìn)程描述符esp從內(nèi)核態(tài)進(jìn)入中斷/異常從用戶態(tài)進(jìn)入中斷/異常Errorcodeespxlanchen@2007.9.2735LinuxOperatingSystemAnalysis從中斷/異常返回中斷/異常處理完后,相應(yīng)的處理程序會(huì)執(zhí)行一條iret匯編指令,這條匯編指令讓CPU控制單元做如下事情:1,用保存在棧中的值裝載cs、eip和eflags寄存器。如果一個(gè)硬件出錯(cuò)碼曾被壓入棧中,那么彈出這個(gè)硬件出錯(cuò)碼2,檢查處理程序的特權(quán)級(jí)是否等于cs中最低兩位的值(這意味著進(jìn)程在被中斷的時(shí)候是運(yùn)行在內(nèi)核態(tài)還是用戶態(tài))。若是,iret終止執(zhí)行;否則,轉(zhuǎn)入3xlanchen@2007.9.2736LinuxOperatingSystemAnalysis3,從棧中裝載ss和esp寄存器。這步意味著返回到與舊特權(quán)級(jí)相關(guān)的棧4,檢查ds、es、fs和gs段寄存器的內(nèi)容,如果其中一個(gè)寄存器包含的選擇符是一個(gè)段描述符,并且特權(quán)級(jí)比當(dāng)前特權(quán)級(jí)高,則清除相應(yīng)的寄存器。這么做是防止懷有惡意的用戶程序利用這些寄存器訪問內(nèi)核空間xlanchen@2007.9.2737LinuxOperatingSystemAnalysis中斷和異常處理程序的嵌套執(zhí)行當(dāng)內(nèi)核處理一個(gè)中斷或異常時(shí),就開始了一個(gè)新的內(nèi)核控制路徑當(dāng)CPU正在執(zhí)行一個(gè)與中斷相關(guān)的內(nèi)核控制路徑時(shí),linux不允許進(jìn)程切換。不過,一個(gè)中斷處理程序可以被另外一個(gè)中斷處理程序中斷,這就是中斷的嵌套執(zhí)行xlanchen@2007.9.2738LinuxOperatingSystemAnalysis搶占原則普通進(jìn)程可以被中斷或異常處理程序打斷異常處理程序可以被中斷程序打斷中斷程序只可能被其他的中斷程序打斷Linux允許中斷嵌套的原因提高可編程中斷控制器和設(shè)備控制器的吞吐量實(shí)現(xiàn)了一種沒有優(yōu)先級(jí)的中斷模型xlanchen@2007.9.2739LinuxOperatingSystemAnalysis初始化中斷描述符表內(nèi)核啟動(dòng)中斷前,必須初始化IDT,然后把IDT的基地址裝載到idtr寄存器中int指令允許用戶進(jìn)程發(fā)出一個(gè)中斷信號(hào),其值可以是0-255的任意一個(gè)向量。 所以,為了防止用戶用int指令非法模擬中斷和異常,IDT的初始化時(shí)要很小心的設(shè)置特權(quán)級(jí)然而用戶進(jìn)程有時(shí)必須要能發(fā)出一個(gè)編程異常。為了做到這一點(diǎn),只要把相應(yīng)的中斷或陷阱門描述符的特權(quán)級(jí)設(shè)置成3xlanchen@2007.9.2740LinuxOperatingSystemAnalysis初始化中斷描述符表Linux中的中斷門、陷阱門和系統(tǒng)門定義中斷門用戶態(tài)的進(jìn)程不能訪問的一個(gè)Intel中斷門(特權(quán)級(jí)為0),所有的中斷都通過中斷門激活,并全部在內(nèi)核態(tài)系統(tǒng)門用戶態(tài)的進(jìn)程可以訪問的一個(gè)Intel陷阱門(特權(quán)級(jí)為3),通過系統(tǒng)門來激活4個(gè)linux異常處理程序,它們的向量是3,4,5和128。因此,在用戶態(tài)下可以發(fā)布int3,into,bound和int$0x80四條匯編指令陷阱門用戶態(tài)的進(jìn)程不能訪問的一個(gè)Intel陷阱門(特權(quán)級(jí)為0),大部分linux異常處理程序通過陷阱門激活xlanchen@2007.9.2741LinuxOperatingSystemAnalysis初始化中斷描述符表下列體系結(jié)構(gòu)相關(guān)的函數(shù)用來在IDT中設(shè)置門不同的是系統(tǒng)門中特權(quán)級(jí)對(duì)應(yīng)的位DPL被置成3。三個(gè)函數(shù)都把相應(yīng)的門中的段描述符設(shè)置成內(nèi)核代碼段的選擇符,偏移字段設(shè)置成addr。xlanchen@2007.9.2742LinuxOperatingSystemAnalysisxlanchen@2007.9.2743LinuxOperatingSystemAnalysisIDT的初步初始化(head.S)用ignore_int()函數(shù)填充256個(gè)idt_table表項(xiàng)xlanchen@2007.9.2744LinuxOperatingSystemAnalysisxlanchen@2007.9.2745LinuxOperatingSystemAnalysisStart_kernel中的IDT表初始化xlanchen@2007.9.2746LinuxOperatingSystemAnalysisTrap_init系統(tǒng)調(diào)用20個(gè)異常源文件xlanchen@2007.9.2747LinuxOperatingSystemAnalysisInit_IRQ中斷源文件xlanchen@2007.9.2748LinuxOperatingSystemAnalysis異常處理CPU產(chǎn)生的大部分異常都由linux解釋為出錯(cuò)條件。

當(dāng)一個(gè)異常發(fā)生時(shí),內(nèi)核就向引起異常的進(jìn)程發(fā)送一個(gè)信號(hào)通知它發(fā)生了一個(gè)反常條件異常處理有一個(gè)標(biāo)準(zhǔn)的結(jié)構(gòu),由三部分組成在內(nèi)核態(tài)堆棧中保存大多數(shù)寄存器的內(nèi)容調(diào)用C語言的函數(shù)通過ret_from_exception()從異常處理程序退出觀察entry.S,并找到C語言函數(shù)的定義之處xlanchen@2007.9.2749LinuxOperatingSystemAnalysis此處,去調(diào)用相應(yīng)的C語言編寫的處理函數(shù)pt_regs指針出錯(cuò)碼xlanchen@2007.9.2750LinuxOperatingSystemAnalysis此時(shí)的內(nèi)核態(tài)堆棧ssespeflagcseiporig_eax:0esdseaxebpediesiedxecxebxerror_codePointer返回地址硬件自動(dòng)保存error_code代碼手工壓入esp高地址低地址進(jìn)程描述符pt_regs指針Errorc_ode拷貝完后,被設(shè)為-1用于傳遞Errorc_odexlanchen@2007.9.2751LinuxOperatingSystemAnalysispt_regs結(jié)構(gòu)(恢復(fù)現(xiàn)場(chǎng)所需的上下文)棧底(高地址)棧頂(低地址)xlanchen@2007.9.2752LinuxOperatingSystemAnalysis異常處理當(dāng)C函數(shù)終止時(shí),根據(jù)堆棧中的返回地址,CPU從call*%edi這條指令的下一條指令開始繼續(xù)執(zhí)行,即:addl$8,%espjmp

ret_from_exceptionaddl$8,%esp的意思是堆棧指針+8,即彈出了pointer和error_code,此時(shí)堆棧中內(nèi)容為ssespeflagcseiporgi_eax(-1)esdseaxebpediesiedxecxebxerror_codePointer返回地址硬件自動(dòng)保存將由iret指令負(fù)責(zé)彈出前面的匯編手工壓入,將由restore_all負(fù)責(zé)彈出esp進(jìn)程描述符xlanchen@2007.9.2753LinuxOperatingSystemAnalysis中斷處理中斷跟異常不同,它并不是表示程序出錯(cuò), 而是硬件設(shè)備有所動(dòng)作,所以不是簡(jiǎn)單地往當(dāng)前進(jìn)程發(fā)送一個(gè)信號(hào)就OK的主要有三種類型的中斷:I/O設(shè)備發(fā)出中斷請(qǐng)求時(shí)鐘中斷處理器間中斷(在SMP,SymmetricMultiprocessor上才會(huì)有這種中斷)xlanchen@2007.9.2754LinuxOperatingSystemAnalysisI/O中斷處理I/O中斷處理程序必須足夠靈活以給多個(gè)設(shè)備同時(shí)提供服務(wù)比如幾個(gè)設(shè)備可以共享同一個(gè)IRQ線

(2個(gè)8359級(jí)聯(lián)也只能提供15根IRQ線,所以外設(shè)共享IRQ線是很正常的)

這就意味著僅僅中斷向量解決不了全部問題xlanchen@2007.9.2755LinuxOperatingSystemAnalysis靈活性以兩種不同的方式達(dá)到IRQ共享:

中斷處理程序執(zhí)行多個(gè)中斷服務(wù)例程(interruptserviceroutines,ISRs)。每個(gè)ISR是一個(gè)與單獨(dú)設(shè)備(共享IRQ線)相關(guān)的函數(shù)IRQ動(dòng)態(tài)分配:一條IRQ線在可能的最后時(shí)刻才與一個(gè)設(shè)備相關(guān)聯(lián)xlanchen@2007.9.2756LinuxOperatingSystemAnalysis為了保證系統(tǒng)對(duì)外部的響應(yīng),一個(gè)中斷處理程序必須被盡快的完成。因此,把所有的操作都放在中斷處理程序中并不合適Linux中把緊隨中斷要執(zhí)行的操作分為三類緊急的(critical)

一般關(guān)中斷運(yùn)行。諸如對(duì)PIC應(yīng)答中斷,對(duì)PIC或是硬件控制器重新編程,或者修改由設(shè)備和處理器同時(shí)訪問的數(shù)據(jù)xlanchen@2007.9.2757LinuxOperatingSystemAnalysis非緊急的(noncritical)

如修改那些只有處理器才會(huì)訪問的數(shù)據(jù)結(jié)構(gòu)(例如按下一個(gè)鍵后讀掃描碼),這些也要很快完成,因此由中斷處理程序立即執(zhí)行,不過一般在開中斷的情況下xlanchen@2007.9.2758LinuxOperatingSystemAnalysis非緊急可延遲的(noncriticaldeferrable)

如把緩沖區(qū)內(nèi)容拷貝到某個(gè)進(jìn)程的地址空間(例如把鍵盤緩沖區(qū)內(nèi)容發(fā)送到終端處理程序進(jìn)程)。這些操作可以被延遲較長(zhǎng)的時(shí)間間隔而不影響內(nèi)核操作,有興趣的進(jìn)程將會(huì)等待數(shù)據(jù)。內(nèi)核用下半部分這樣一個(gè)機(jī)制來在一個(gè)更為合適的時(shí)機(jī)用獨(dú)立的函數(shù)來執(zhí)行這些操作xlanchen@2007.9.2759LinuxOperatingSystemAnalysis不管引起中斷的設(shè)備是什么,所有的I/O中斷處理程序都執(zhí)行四個(gè)相同的基本操作1,在內(nèi)核態(tài)堆棧保存IRQ的值和寄存器的內(nèi)容2,為正在給IRQ線服務(wù)的PIC發(fā)送一個(gè)應(yīng)答,這將允許PIC進(jìn)一步發(fā)出中斷3,執(zhí)行共享這個(gè)IRQ的所有設(shè)備的中斷服務(wù)例程4,跳到ret_from_intr()的地址xlanchen@2007.9.2760LinuxOperatingSystemAnalysis中斷處理示意圖xlanchen@2007.9.2761LinuxOperatingSystemAnalysisLinux中的中斷向量分配表xlanchen@2007.9.2762LinuxOperatingSystemAnalysisLinux中的設(shè)備中斷IRQ號(hào)與I/O設(shè)備之間的對(duì)應(yīng)關(guān)系是在初始化每個(gè)設(shè)備驅(qū)動(dòng)程序時(shí)建立的xlanchen@2007.9.2763LinuxOperatingSystemAnalysis中斷處理系統(tǒng)初始化時(shí),調(diào)用init_IRQ()函數(shù)用新的中斷門替換臨時(shí)中斷門來更新IDT

這段代碼在interrupt數(shù)組中找到用于建立中斷門的中斷處理程序地址。xlanchen@2007.9.2764LinuxOperatingSystemAnalysisInterrupt數(shù)組的定義Linux中Interrupt數(shù)組的定義比較隱晦源文件xlanchen@2007.9.2765LinuxOperatingSystemAnalysis每個(gè)中斷程序入口的定義源文件源文件xlanchen@2007.9.2766LinuxOperatingSystemAnalysis因此,每個(gè)中斷程序入口操作為:將中斷向量入棧保存所有其他寄存器調(diào)用do_IRQ跳轉(zhuǎn)到ret_from_intrxlanchen@2007.9.2767LinuxOperatingSystemAnalysisdo_IRQdo_IRQ使用的數(shù)據(jù)結(jié)構(gòu)(體系結(jié)構(gòu)無關(guān)):irq_desc數(shù)組包含了NR_IRQS(通常為224)個(gè)irq_desc_t描述符xlanchen@2007.9.2768LinuxOperatingSystemAnalysisirq_desc_t和irq_desc每一個(gè)中斷號(hào)具有一個(gè)描述符,使用action鏈表連接共享同一個(gè)中斷號(hào)的多個(gè)設(shè)備和中斷中斷控制器處理例程xlanchen@2007.9.2769LinuxOperatingSystemAnalysisirqaction數(shù)據(jù)結(jié)構(gòu)用來實(shí)現(xiàn)IRQ的共享,維護(hù)共享irq的特定設(shè)備和特定中斷,所有共享一個(gè)irq的鏈接在一個(gè)action表中,由中斷描述符中的action指針指向鏈表中斷處理程序xlanchen@2007.9.2770LinuxOperatingSystemAnalysis設(shè)置irqaction的函數(shù)…xlanchen@2007.9.2771LinuxOperatingSystemAnalysishw_interrupt_type數(shù)據(jù)結(jié)構(gòu)為特定PIC編寫的低級(jí)I/O例程xlanchen@2007.9.2772LinuxOperatingSystemAnalysis8259A的hw_interrupt_type8259A的中斷控制操作所有連接到8259A的外設(shè)中斷都要設(shè)置xlanchen@2007.9.2773LinuxOperatingSystemAnalysis例如:xlanchen@2007.9.2774LinuxOperatingSystemAnalysis中斷處理過程在調(diào)用do_IRQ之前,要為中斷處理程序保存寄存器在interrupt數(shù)組中定義的中斷處理程序中每個(gè)入口地址轉(zhuǎn)換成匯編碼是如下的一些指令

IRQn_interrupt:

pushl$n-256

jmp

common_interrupt

這里對(duì)所有的中斷處理程序都執(zhí)行相同的代碼

common_interrupt: SAVE_ALL calldo_IRQ

jmp$ret_from_intrxlanchen@2007.9.2775LinuxOperatingSystemAnalysisssespeflagcseip$n-256esdseaxebpediesiedxecxebx返回地址Pointer硬件自動(dòng)保存SAVE_ALLesp進(jìn)程描述符do_IRQ執(zhí)行時(shí)內(nèi)核態(tài)的堆棧do_IRQ()的函數(shù)聲明從do_IRQ返回后要執(zhí)行的指令地址ret_from_intrxlanchen@2007.9.2776LinuxOperatingSystemAnalysis中斷處理do_IRQ()函數(shù)的等價(jià)代碼:

int

irq=regs.orig_eax&0xff; //1

irq_desc[irq].handler->ack(irq); //2 handle_IRQ_event(irq,®s,irq_desc[irq].action);//3

irq_desc[irq].handler->end(irq); //4

處理下半部分 //5 1句將$n-255轉(zhuǎn)換成n,取得對(duì)應(yīng)的中斷向量

2句應(yīng)答PIC的中斷,并禁用這條IRQ線。(為串行處理同類型中斷) 3句調(diào)用handle_IRQ_event()執(zhí)行中斷服務(wù)例程

4句通知PIC重新激活這條IRQ線,允許處理同類型中斷xlanchen@2007.9.2777LinuxOperatingSystemAnalysis中斷服務(wù)例程一個(gè)中斷服務(wù)例程實(shí)現(xiàn)一種特定設(shè)備的操作,handle_IRQ_evnet()函數(shù)依次調(diào)用這些設(shè)備例程這個(gè)函數(shù)本質(zhì)上執(zhí)行了如下核心代碼: do{

action->handler(irq,action->dev_id,regs);

action=action->next;

}while(action)xlanchen@2007.9.2778LinuxOperatingSystemAnalysis軟中斷、tasklet以及下半部分對(duì)內(nèi)核來講,可延遲中斷不是很緊急,可以將它們從中斷處理例程中抽取出來,保證較短的中斷響應(yīng)時(shí)間Linux2.4提供了三種方法軟中斷、tasklet以及下半部分Tasklet在軟中斷之上實(shí)現(xiàn)下半部分通過tasklet實(shí)現(xiàn)一般原則:在同一個(gè)CPU上軟中斷/tasklet/下半部分不嵌套軟中斷和下半部分由內(nèi)核靜態(tài)分配(編譯時(shí)確定)Tasklet可以在運(yùn)行時(shí)分配和初始化(例如裝入一個(gè)內(nèi)核模塊時(shí))xlanchen@2007.9.2779LinuxOperatingSystemAnalysis一般而言,可延遲函數(shù)上可以執(zhí)行4種操作初始化:定義一個(gè)新的可延遲函數(shù),通常在內(nèi)核初始化時(shí)進(jìn)行激活:設(shè)置可延遲函數(shù)在下一輪處理中執(zhí)行屏蔽:有選擇的屏蔽一個(gè)可延遲函數(shù),這樣即使被激活也不會(huì)被運(yùn)行執(zhí)行:在特定的時(shí)間執(zhí)行可延遲函數(shù)xlanchen@2007.9.2780LinuxOperatingSystemAnalysis軟中斷Linux2.4使用有限個(gè)軟中斷,目前只有4個(gè)在softirq_vec中定義優(yōu)先級(jí)0:處理高優(yōu)先級(jí)的tasklet和下半部分優(yōu)先級(jí)1:把數(shù)據(jù)包傳送到網(wǎng)卡優(yōu)先級(jí)2:從網(wǎng)卡接受數(shù)據(jù)包優(yōu)先級(jí)3:處理tasklet優(yōu)先級(jí)對(duì)應(yīng)于softirq_vec的下標(biāo)軟中斷函數(shù)及其參數(shù)xlanchen@2007.9.2781LinuxOperatingSystemAnalysis軟中斷的初始化初始化軟中斷函數(shù)分別在softirq_init和net_dev_init中初始化xlanchen@2007.9.2782LinuxOperatingSystemAnalysis內(nèi)核中用來控制軟中斷的數(shù)據(jù)結(jié)構(gòu)irq_statirq_stat數(shù)組用來描述各個(gè)CPU的irq處理狀態(tài)對(duì)于單CPU而言,數(shù)組長(zhǎng)度為1哪些軟中斷被掛起禁止軟中斷?哪個(gè)進(jìn)程執(zhí)行可延遲函數(shù)?對(duì)這個(gè)數(shù)據(jù)的調(diào)控,用來激活一個(gè)軟中斷:__cpu_raise_softirqcpu_raise_softirq還可能喚醒這個(gè)進(jìn)程ksoftirqdxlanchen@2007.9.2783LinuxOperatingSystemAnalysis軟中斷的檢查在某些特定的時(shí)機(jī),會(huì)檢查是否有軟中斷被掛起調(diào)用local_bh_enable重新激活軟中斷時(shí)當(dāng)do_IRQ完成了I/O中斷的處理時(shí)當(dāng)那個(gè)特定的進(jìn)程ksoftirqd被喚醒時(shí)…這種時(shí)機(jī),稱為檢查點(diǎn)xlanchen@2007.9.2784LinuxOperatingSystemAnalysis在每個(gè)檢查點(diǎn)若有軟中斷被掛起,就調(diào)用do_softirq判斷是否可以執(zhí)行軟中斷若可以,就執(zhí)行軟中斷執(zhí)行后,若發(fā)現(xiàn)又有新的軟中斷被激活,就喚醒ksoftirqd進(jìn)程,來觸發(fā)do_softirq的另一次執(zhí)行xlanchen@2007.9.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論