計(jì)算機(jī)操作系統(tǒng)(第二版)課件:中斷和時(shí)鐘_第1頁
計(jì)算機(jī)操作系統(tǒng)(第二版)課件:中斷和時(shí)鐘_第2頁
計(jì)算機(jī)操作系統(tǒng)(第二版)課件:中斷和時(shí)鐘_第3頁
計(jì)算機(jī)操作系統(tǒng)(第二版)課件:中斷和時(shí)鐘_第4頁
計(jì)算機(jī)操作系統(tǒng)(第二版)課件:中斷和時(shí)鐘_第5頁
已閱讀5頁,還剩28頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

中斷和時(shí)鐘1.中斷的基本概念中斷是指計(jì)算機(jī)運(yùn)行過程中,出現(xiàn)某些意外情況需主機(jī)干預(yù)時(shí),機(jī)器能自動暫停正在運(yùn)行的程序并轉(zhuǎn)入處理新情況的程序,處理完畢后又返回原被暫停的程序繼續(xù)運(yùn)行。程序運(yùn)行過程中,如果系統(tǒng)外部、系統(tǒng)內(nèi)部或者當(dāng)前運(yùn)行程序本身出現(xiàn)緊急事件,處理機(jī)將立即暫停當(dāng)前程序的運(yùn)行,自動轉(zhuǎn)入相應(yīng)的處理程序(中斷服務(wù)程序),待處理完后,再返回原來的程序運(yùn)行,這整個(gè)過程稱為程序中斷。2.現(xiàn)代計(jì)算機(jī)中采用中斷系統(tǒng)的主要目的①提高計(jì)算機(jī)系統(tǒng)效率②維持系統(tǒng)可靠正常工作③滿足實(shí)時(shí)處理要求④提供故障現(xiàn)場處理手段3.中斷的分類中斷會改變處理器執(zhí)行指令的順序,通常與CPU芯片內(nèi)部或外部硬件電路產(chǎn)生的電信號相對應(yīng)。中斷可以分為中斷和異常兩類:中斷一般是異步的,由硬件隨機(jī)產(chǎn)生,在程序執(zhí)行的任何時(shí)候可能出現(xiàn);異常一般是同步的,在(特殊的或出錯的)指令執(zhí)行時(shí)由CPU控制單元產(chǎn)生。在Intel系列CPU中把中斷和異常分為以下幾類:(1)中斷

(2)異常(1)中斷又進(jìn)一步分為可屏蔽中斷和非屏蔽中斷:①可屏蔽中斷:可由程序控制其屏蔽性的中斷稱為可屏蔽中斷,處于屏蔽狀態(tài)時(shí),處理機(jī)將忽略該中斷信號。I/O設(shè)備發(fā)出的所有中斷請求都屬于可屏蔽中斷。②非屏蔽中斷:與可屏蔽中斷相對應(yīng),不能由程序控制其屏蔽性,處理機(jī)一定要立即處理的中斷稱為非屏蔽中斷或不可屏蔽中斷。非屏蔽中斷數(shù)量較少,通常是由一些緊急事件引發(fā)的中斷,如斷電、電源故障等情況,需要處理器立即處理。(2)異常:異常又可進(jìn)一步分為以下幾類:1)處理器探測異常:當(dāng)處理器執(zhí)行指令時(shí)探測到的一個(gè)反常條件所產(chǎn)生的異常??梢赃M(jìn)一步分為三類,這取決于處理器控制單元產(chǎn)生異常時(shí)保存在內(nèi)核態(tài)堆棧eip寄存器中的值。①故障:保存在eip中的值是引起故障的指令地址,因此,當(dāng)異常處理程序終止時(shí),那條指令會被重新執(zhí)行。②陷阱:保存在eip中的值是一個(gè)隨后要執(zhí)行的指令地址。只有當(dāng)沒有必要重新執(zhí)行已終止的指令時(shí),才觸發(fā)陷阱。陷阱的主要用途是為了調(diào)試程序。在這種情況下,中斷信號的作用是通知調(diào)試程序一條特殊指令已被執(zhí)行(例如到了一個(gè)程序內(nèi)的斷點(diǎn))。一旦用戶檢查到調(diào)試程序所提供的數(shù)據(jù),它就可能要求被調(diào)試程序從下一條執(zhí)行重新開始執(zhí)行。③異常中止:發(fā)生一個(gè)嚴(yán)重的錯誤,控制單元出了問題,不能在eip寄存器中保存引起異常的指令所在的確切位置。異常中止用于報(bào)告嚴(yán)重的錯誤,如硬件故障或系統(tǒng)表中無效的值或不一致的值。由控制單元發(fā)生的這個(gè)中斷信號是緊急信號,用來把控制權(quán)切換到相應(yīng)的異常中止處理程序,這個(gè)異常中止處理程序除了強(qiáng)制受影響的進(jìn)程終止外,沒有別的選擇。(2)異常:異常又可進(jìn)一步分為以下幾類:2)編程異常由編程者發(fā)出請求產(chǎn)生的異常。是由int或int3指令觸發(fā)的;當(dāng)into(檢查溢出)和bound(檢查地址出界)指令檢查的條件不為真時(shí),也引起編程異常??刂茊卧丫幊坍惓W鳛橄葳鍋硖幚?。編程異常通常也叫做軟中斷。這樣的異常有兩種常用的用途:執(zhí)行系統(tǒng)調(diào)用及給調(diào)試程序通報(bào)一個(gè)特定的事件。4.中斷向量為了方便異常和中斷的處理,系統(tǒng)為每個(gè)異常和中斷都賦予了一個(gè)唯一的標(biāo)識號,稱為向量(vector),將其用作中斷描述符表IDT(InterruptDescriptorTable)中的一個(gè)索引號,以快速定位一個(gè)異?;蛑袛嗟奶幚沓绦虻娜肟诘刂贰O到y(tǒng)允許的向量號范圍是0~255,其中0~31保留用作80x86處理器定義的異常和中斷,32~255用于用戶定義的中斷。這些中斷通常用于外部I/O設(shè)備,使得這些設(shè)備可以通過外部硬件中斷機(jī)制向處理器發(fā)送中斷。表2-3以linux系統(tǒng)為例,給出了為80x86定義的異常和非屏蔽中斷分配的向量。向量范圍用途0~19(0x0~0x13)非屏蔽中斷和異常20~31(0x14~0x1f)Intel保留32~127(0x20~0x7f)外部中斷(IRQ)128(0x80)用于系統(tǒng)調(diào)用的可編程異常(參見第十章)129~238(0x81~0xee)外部中斷(IRQ)239(0xef)本地APIC時(shí)鐘中斷(參見第六章)240(0xf0)本地APIC高溫中斷(在Pentium4模型中引入)241~250(0xf0~0xfa)由Linux留作將來使用251~253(0xfb~0xff)處理器間中斷(參見本章后面“處理器間中斷處理”一節(jié))254(0xfe)本地APIC錯誤中斷(當(dāng)本地APIC檢測到一個(gè)錯誤條件是產(chǎn)生)255(0xff)本地APIC偽中斷(CPU屏蔽某個(gè)中斷時(shí)產(chǎn)生)表2-4給出了中斷請求與硬件設(shè)備的對應(yīng)表。IRQINT硬件設(shè)備032時(shí)鐘133鍵盤234PIC級聯(lián)335第二串口436第一串口638軟盤840系統(tǒng)時(shí)鐘1042網(wǎng)絡(luò)端口1143USB端口、聲卡1244PS/2鼠標(biāo)1345數(shù)學(xué)協(xié)處理器1446EIDE磁盤控制器的一級鏈接1547EIDE磁盤控制器的二級鏈接5.中斷描述符表(InterruptDescriptorTable,IDT)中斷描述符表(實(shí)模式中稱為中斷向量表)的作用是將每個(gè)異?;蛑袛嘞蛄糠謩e與它們的處理程序聯(lián)系起來。由于系統(tǒng)中最多只有256個(gè)中斷或異常向量,因此IDT中的描述符個(gè)數(shù)不會超出256個(gè),不過IDT中所有空描述符項(xiàng)應(yīng)該設(shè)置其存在位(標(biāo)志)為0。、在實(shí)地址模式中,CPU把內(nèi)存的從0開始的1K字節(jié)用于存放中斷向量表,表中每個(gè)表項(xiàng)占四個(gè)字節(jié),由兩個(gè)字節(jié)的段地址和兩個(gè)字節(jié)的偏移量組成,這樣構(gòu)成的地址便是相應(yīng)中斷處理程序的入口地址。但是,在保護(hù)模式下,中斷處理程序入口地址的偏移量需要4個(gè)字節(jié),另外還要有反映模式切換的信息,因此表項(xiàng)長度擴(kuò)展為8個(gè)字節(jié),此時(shí)中斷向量表也改稱為中斷描述符表IDT,其中的每個(gè)表項(xiàng)叫做一個(gè)門描述符(gatedescriptor),“門”的含義是當(dāng)中斷發(fā)生時(shí)必須先通過這些門,然后才能進(jìn)入相應(yīng)的處理程序。保護(hù)模式下IDT可以駐留在內(nèi)存空間的任何地方,處理器使用IDTR寄存器來定位IDT的位置,該寄存器是一個(gè)48位的寄存器,其低16位保存中斷描述符表的大小,高32位保存IDT的基址。由于每個(gè)描述符的長度是8字節(jié),因此IDT的基地址應(yīng)對齊在8字節(jié)邊界上以提高訪問效率。限長值是以字節(jié)為單位的IDT的長度。與IDTR寄存器相關(guān)的指令有LIDT和SIDT。LIDT指令用于把內(nèi)存中的IDT的限長值和基地址加載到IDTR寄存器中,該指令僅能由當(dāng)前特權(quán)級CPL是0的代碼執(zhí)行,通常在操作系統(tǒng)初始創(chuàng)建IDT時(shí)執(zhí)行。SIDT指令用于把IDTR中的基地址和限長值復(fù)制到內(nèi)存中,該指令可在任何特權(quán)級上執(zhí)行。下面介紹保護(hù)模式下主要的門描述符:介紹保護(hù)模式下主要的門描述符:(1)中斷門(Interruptgate)中斷門的類型碼為110,其中包含了一個(gè)中斷或異常處理程序所在段的選擇符和段內(nèi)偏移量,如圖2-7上所示。當(dāng)控制權(quán)通過中斷門進(jìn)入中斷處理程序時(shí),處理器清除IF標(biāo)志,即關(guān)中斷,以避免嵌套中斷的發(fā)生。中斷門中的DPL(DescriptorPrivilegeLevel)為0,因此,用戶態(tài)的進(jìn)程不能訪問中斷門。所有的中斷處理程序都由中斷門激活,并全部限制在內(nèi)核態(tài)中執(zhí)行。(2)陷阱門(Trapgate)陷阱門的類型碼為111,與中斷門類似,兩者唯一的區(qū)別是,控制權(quán)通過陷阱門進(jìn)入處理程序時(shí)維持IF標(biāo)志位不變,即不關(guān)中斷,其結(jié)構(gòu)如圖2-7中所示。(3)系統(tǒng)門(Systemgate)這是Linux內(nèi)核特別設(shè)置的,用來讓用戶態(tài)的進(jìn)程訪問陷阱門,因此,其門描述符的DPL為3。通過系統(tǒng)門來激活4個(gè)Linux異常處理程序,它們的向量是3、4、5及128,即在用戶態(tài)下可以執(zhí)行int3、into、bound及int0x80四條匯編指令。其結(jié)構(gòu)如圖2-7下所示。6.傳統(tǒng)的中斷控制器:8259A傳統(tǒng)的中斷控制器使用兩片8259A以“級聯(lián)”的方式連接在一起,如圖2-8所示。每個(gè)芯片可以處理最多8個(gè)不同的IRQ線,為了增加IRQ線,使用2個(gè)8259A芯片以級聯(lián)的方式進(jìn)行鏈接,從8259的輸出引角連接主8259的IRQ輸入引腳,因此,一共可以處理最多15個(gè)不同的IRQ線。圖2-8基于8259的中斷控制器簡要說明下CPU的中斷處理過程假設(shè)內(nèi)核已完成初始化,CPU在保護(hù)模式下運(yùn)行。當(dāng)CPU正常執(zhí)行完一條指令后,cs和eip這對寄存器包含了下一條將要執(zhí)行的指令的邏輯地址。在執(zhí)行這條指令之前,CPU控制單元會檢查在運(yùn)行前一條指令時(shí)是否發(fā)生了一個(gè)中斷或者異常。如果確定發(fā)生了一個(gè)中斷或異常,那么CPU控制單元將依次執(zhí)行下列操作:(1)確定與中斷或者異常關(guān)聯(lián)的向量i(0~255);(2)讀idtr寄存器指向的IDT表中的第i項(xiàng);(3)從gdtr寄存器獲得GDT的基地址,并查找GDT,以讀取IDT表項(xiàng)中的段選擇符所標(biāo)識的段描述符;(4)確定中斷是由授權(quán)的發(fā)生源發(fā)出的:(5)檢查是否發(fā)生了特權(quán)級的變化,一般指是否由用戶態(tài)陷入了內(nèi)核態(tài),如果是,則控制單元必須開始使用與新的特權(quán)級相關(guān)的堆棧:讀tr寄存器,訪問運(yùn)行進(jìn)程的tss段,找到與新特權(quán)級相關(guān)的棧段和棧指針的值;然后用這些值裝載CPU的ss和esp寄存器;最后在新的棧中保存ss和esp以前的值,這些值指明了與舊特權(quán)級相關(guān)的棧的地址。(6)若發(fā)生的是故障,用引起異常的指令地址修改cs和eip寄存器的值,以使得這條指令在異常處理結(jié)束后能被再次執(zhí)行;(7)在棧中保存eflags、cs和eip的內(nèi)容;(8)如果異常產(chǎn)生一個(gè)硬件出錯碼,則將它保存在棧中;(9)裝載cs和eip寄存器,其值分別是IDT表中第i項(xiàng)門描述符的段選擇符和偏移量字段。這對寄存器值給出中斷或者異常處理程序的第一條指令的地址。之后CPU就將去執(zhí)行中斷或異常處理程序了。當(dāng)中斷或異常處理程序執(zhí)行完成后,相應(yīng)的處理程序會執(zhí)行一條iret匯編指令,實(shí)現(xiàn)從中斷或異常的返回。iret指令將完成如下工作:(1)用保存在棧中的值裝載cs、eip和eflags寄存器。如果一個(gè)硬件出錯碼曾被壓入棧中,那么彈出這個(gè)硬件出錯碼;(2)檢查處理程序的特權(quán)級是否等于cs中最低兩位的值(即判斷進(jìn)程在被中斷時(shí)是否運(yùn)行在內(nèi)核態(tài))。若是,iret終止執(zhí)行;否則,轉(zhuǎn)入(3);(3)從棧中裝載ss和esp寄存器,即返回到與舊特權(quán)級相關(guān)的棧;(4)檢查ds、es、fs和gs段寄存器的內(nèi)容,如果其中一個(gè)寄存器包含的選擇符是一個(gè)段描述符,并且特權(quán)級比當(dāng)前特權(quán)級高,則清除相應(yīng)的寄存器,以防止懷有惡意的用戶程序利用這些寄存器訪問內(nèi)核空間。中斷舉例,如圖2-9。分析A,B,C,D在互相搶占上的關(guān)系假設(shè):2個(gè)interrupt,記為A和B2個(gè)process,記為C和D1、假設(shè)某個(gè)時(shí)刻C占用CPU運(yùn)行,此時(shí)A中斷發(fā)生,C被A搶占,A得以在CPU上執(zhí)行。由于Linux不為中斷處理程序設(shè)置獨(dú)立堆棧,A只能使用C的kernelstack作為自己的運(yùn)行棧。2、無論如何,Linux的interruptA絕對不會被某個(gè)進(jìn)程C或者D搶占!這是由于所有已經(jīng)啟動的interrupt,不管是interrupt之間切換,還是在某個(gè)interrupt中執(zhí)行代碼的過程,決不可能插入scheduler調(diào)度例程的調(diào)用。除非interrupt主動或者被動阻塞進(jìn)入睡眠,喚起scheduler,但這是必須避免的,危險(xiǎn)性見第3點(diǎn)說明。3、關(guān)于第2點(diǎn)的解釋:首先,interrupt沒有堆棧,A中斷是“借”了C的堆棧運(yùn)行的,若允許A“阻塞”或“睡眠”,則C將被迫阻塞或睡眠,僅當(dāng)A被“喚醒”C才被喚醒;而“喚醒”后,A將按照C在就緒隊(duì)列中的順序被調(diào)度。這既損害了A的利益也污染了C的kernelstack。其次,如果interruptA由于阻塞或是其他原因睡眠,外界對系統(tǒng)的響應(yīng)能力將變得不可忍受4、那么interruptA和B的關(guān)系又如何呢?由于可能在中斷的某個(gè)步驟打開了CPU的IFflag標(biāo)志,這使得在A過程中,B的irqline已經(jīng)觸發(fā)了PIC,進(jìn)而觸發(fā)了CPUIRQpin,使得CPU執(zhí)行中斷B,這是中斷上下文的嵌套過程。5、通常Linux不對不同的interrupt設(shè)置優(yōu)先級,這種任意的嵌套是允許的圖2-9中斷舉例2.3.2系統(tǒng)調(diào)用(以Linux/openEuler為例)系統(tǒng)調(diào)用概念系統(tǒng)功能調(diào)用是用戶在程序一級請求操作系統(tǒng)服務(wù)的一種手段,它是帶有一定功能號的“訪管指令”。其功能是由操作系統(tǒng)中的程序完成的。INT指令Dos:INT21HLinux:INT80Htrap指令┇fork()┇在應(yīng)用程序中調(diào)用系統(tǒng)調(diào)用fork(){┇int0x80┇}在libc庫中的封裝例程用戶態(tài)system_call:┇sys_fork()

┇ret_from_sys_calliretsys_fork(){┇}內(nèi)核態(tài)系統(tǒng)調(diào)用處理程序系統(tǒng)調(diào)用服務(wù)例程2.系統(tǒng)調(diào)用執(zhí)行流程系統(tǒng)調(diào)用與API有什么區(qū)別?2.3.2

系統(tǒng)調(diào)用(以Linux/openEuler為例)4.系統(tǒng)調(diào)用號(以Linux/openEuler為例)操作系統(tǒng)為每個(gè)系統(tǒng)調(diào)用都賦予一個(gè)唯一的系統(tǒng)調(diào)用號比如Linux

4.12中:系統(tǒng)調(diào)用號系統(tǒng)調(diào)用名0Read1Write2Open3Close60exit2.3.2

系統(tǒng)調(diào)用(以Linux/openEuler為例)2.3.2系統(tǒng)調(diào)用(以Linux/openEuler為例)5.系統(tǒng)調(diào)用服務(wù)例程與系統(tǒng)調(diào)用入口表①系統(tǒng)調(diào)用服務(wù)例程:完成某個(gè)系統(tǒng)調(diào)用功能的內(nèi)核函數(shù)②系統(tǒng)調(diào)用入口表:記錄了內(nèi)核中所有已注冊過的系統(tǒng)調(diào)用,是系統(tǒng)調(diào)用的跳轉(zhuǎn)表。③Linux系統(tǒng)調(diào)用表保存在linux-4.12/arch/x86/entyr/syscalls/syscall_32.tbl或syscall_64.tbl中

<number><abi><name><entrypoint>3.系統(tǒng)調(diào)用處理程序:

system_call()

int$0x80異常的處理程序,是所有系統(tǒng)調(diào)用的入口點(diǎn)內(nèi)核初始化時(shí)調(diào)用trap_init()函數(shù):設(shè)置中斷描述符相應(yīng)字段

2.3.2系統(tǒng)調(diào)用(以Linux/openEuler為例)3.系統(tǒng)調(diào)用處理程序:

system_call()

segmentselector:內(nèi)核代碼段__KERNEL_CS的段選擇符

offset:指向system_call()異常處理程序的入口地址

type:置為15,表示該異常是一個(gè)陷阱,相應(yīng)處理程序不禁止可屏蔽中斷

DPL(特權(quán)級):置為3,允許用戶程序中執(zhí)行int$0x80存放系統(tǒng)調(diào)用號主要工作:pushl%eax宏SAVE_ALL保護(hù)現(xiàn)場;正確性檢查;依eax中所包含的系統(tǒng)調(diào)用號,調(diào)用其對應(yīng)的服務(wù)例程;系統(tǒng)服務(wù)例程結(jié)束時(shí),通過宏RESTORE_ALL恢復(fù)寄存器;通過iret指令返回。call*SYMBOL_NAME(sys_call_table)(0,%eax,4)#defineSAVE_ALL\cld;\pushl%es;\pushl%ds;\pushl%eax;\pushl%ebp;\pushl%edi;\pushl%esi;\pushl%edx;\pushl%ecx;\pushl%ebx;\movl$(__KERNEL_DS),%edx;\movl%edx,%ds;\movl%edx,%es;3.系統(tǒng)調(diào)用處理程序:

system_call()2.3.2系統(tǒng)調(diào)用(以Linux/openEuler為例)ENTRY(system_call) pushl%eax //保存EAX寄存器的內(nèi)容

SAVE_ALL//保存各通用寄存器的內(nèi)容

GET_CURRENT(%ebx)//獲取調(diào)用進(jìn)程的task_struct結(jié)構(gòu)的指針 ┇cmpl$(NR_syscalls),%eax//檢測系統(tǒng)調(diào)用是否合法系統(tǒng)調(diào)用。

jaebadsys//如果該系統(tǒng)調(diào)用號越界則跳轉(zhuǎn)到標(biāo)號badsys處

testb$0x20,flags(%ebx) //檢測是否設(shè)置了PF_TRACESYS標(biāo)志

jnetracesys//如果設(shè)置了PF_TRACESYS標(biāo)志則跳轉(zhuǎn)到標(biāo)號tracesys處

call*SYMBOL_NAME(sys_call_table)(,%eax,4)//執(zhí)行系統(tǒng)調(diào)用服務(wù)例程

movl%eax,EAX(%esp) //系統(tǒng)調(diào)用返回值進(jìn)棧保存。ret_from_sys_call://系統(tǒng)調(diào)用返回system_call()的源代碼:2.3.2

系統(tǒng)調(diào)用(以Linux/openEuler為例)4.系統(tǒng)調(diào)用參數(shù)傳遞寄存器傳遞:eax:系統(tǒng)調(diào)用號ebx,ecx,edx,esi和edi按照順序存放前五個(gè)參數(shù)對參數(shù)的要求:每個(gè)參數(shù)長度不能超過寄存器長度,即32位;參數(shù)個(gè)數(shù)實(shí)際不能超過5個(gè);5.系統(tǒng)調(diào)用返回值:所有系統(tǒng)調(diào)用返回一個(gè)整數(shù)值:正數(shù)或0表示系統(tǒng)調(diào)用成功結(jié)束負(fù)數(shù)表示出錯,返回的負(fù)值由封裝例程存放在errno變量中返回給應(yīng)用程序如果系統(tǒng)調(diào)用參數(shù)超出5個(gè)怎么辦?2.3.2

系統(tǒng)調(diào)用(以Linux/openEuler為例)fork(){┇int0x80┇}在執(zhí)行int$0x80之前l(fā)ibc庫中的封裝例程設(shè)置16

6.系統(tǒng)調(diào)用執(zhí)行過程intmain(){…getuid();

…}intgetuid(void)

{long_res;…int$0x80;

…}ENTRY(system_call)pushl%eaxSAVE_ALLGET_CURRENT(%ebx)

…callsys_getuid16

…RESTORE_ALLiretasmlinkagelongsys_getuid16(void){return(current_uid);}用戶程序系統(tǒng)調(diào)用處理程序標(biāo)準(zhǔn)C庫內(nèi)核服務(wù)例程getuid():返回調(diào)用進(jìn)程的用戶ID哪個(gè)小組積極來回答?2.3.2

系統(tǒng)調(diào)用(以Linux/openEuler為例)6.系統(tǒng)調(diào)用執(zhí)行流程在封裝例程中含有int$0x80匯編指令代碼int$0x80使該調(diào)用進(jìn)入內(nèi)核:system_call()該系統(tǒng)調(diào)用被執(zhí)行,并返回執(zhí)行結(jié)果該系統(tǒng)調(diào)用由標(biāo)準(zhǔn)C庫的封裝例程(宏)來引導(dǎo)

用戶發(fā)出一個(gè)系統(tǒng)調(diào)用的請求由system_call找到指定的系統(tǒng)調(diào)用服務(wù)例程2.3.2系統(tǒng)調(diào)用(以Linux/openEuler為例)2.3.3計(jì)算機(jī)系統(tǒng)時(shí)鐘計(jì)算機(jī)中很多活動都是由定時(shí)測量來驅(qū)動的,這對用戶常常是不可見的。例如,當(dāng)你停止使用計(jì)算機(jī)的控制臺以后,屏幕會自動關(guān)閉,這得歸因于定時(shí)器,它允許內(nèi)核跟蹤你按鍵或移動鼠標(biāo)后到現(xiàn)在過了多少時(shí)間;如果你收到了一個(gè)來自系統(tǒng)的警告信息,建議你刪除一組不用的文件,這是由于有一個(gè)程序能識別長時(shí)間未被訪問的所有用戶文件。為了進(jìn)行這些操作,程序必須能從每個(gè)設(shè)備或文件中檢索到它們最后被訪問的時(shí)間,即時(shí)間戳,而這些時(shí)間標(biāo)記必須由內(nèi)核自動地設(shè)置。Linux內(nèi)核提供了兩種主要的定時(shí)測量手段:一是獲得當(dāng)前的時(shí)間和日期,包括time(),ftime()以及gettimeofday()等系統(tǒng)調(diào)用;二是維持定時(shí)器,包括settimer(),alarm()等系統(tǒng)調(diào)用。定時(shí)測量是由基于固定頻率振蕩器和計(jì)數(shù)器的幾個(gè)硬件電路完成的。在x86體系結(jié)構(gòu)上,內(nèi)核必須顯式的與以下幾種時(shí)鐘打交道:(1)實(shí)時(shí)時(shí)鐘(RTC)實(shí)時(shí)時(shí)鐘芯片是日常生活中應(yīng)用最為廣泛的消費(fèi)類電子產(chǎn)品之一,它為人們提供精確的實(shí)時(shí)時(shí)間,或者為電子系統(tǒng)提供精確的時(shí)間基準(zhǔn),目前實(shí)時(shí)時(shí)鐘芯片大多采用精度較高的晶體振蕩器作為時(shí)鐘源。有些時(shí)鐘芯片為了在主電源掉電時(shí)還可以工作,需要外加電池供電。為實(shí)現(xiàn)實(shí)時(shí)時(shí)鐘,需要硬件結(jié)構(gòu)晶振的支持。Linux內(nèi)核只使用RTC獲得時(shí)間和日期信息,其對應(yīng)的設(shè)備文件為/dev/rtc,可以通過設(shè)備文件對其編程,內(nèi)核通過0x70和0x71兩個(gè)端口訪問RTC,系統(tǒng)管理員可以通過執(zhí)行時(shí)鐘程序設(shè)置時(shí)鐘。(2)時(shí)間戳計(jì)數(shù)器TSC時(shí)間戳計(jì)數(shù)器記錄自啟動以來處理器消耗的時(shí)鐘周期數(shù)。由于時(shí)間戳計(jì)數(shù)器(TSC)隨著處理器周期速率的比例的變化而變化,因此提供了非常高的精度。TSC通常被用于剖析和監(jiān)測代碼。使用rdtsc指令可測量某段代碼的執(zhí)行時(shí)間,其精度達(dá)到微秒級,TSC的節(jié)拍可以被轉(zhuǎn)化為秒,方法是將其除以CPU時(shí)鐘速率(在linux中,可以從內(nèi)核變量cpu_khz讀?。?。(3)可編程間隔定時(shí)器PIT每個(gè)PC機(jī)中都有一個(gè)PIT,通過IRQ產(chǎn)生周期性的時(shí)鐘中斷信號來充當(dāng)系統(tǒng)定時(shí)器。i386中使用的通常是Intel8254PIT芯片,它的I/O端口地址范圍是40h~43h。8254PIT有3個(gè)計(jì)時(shí)通道,每個(gè)通道都有其不同的用途:通道0用來負(fù)責(zé)更新系統(tǒng)時(shí)鐘。它在每一個(gè)時(shí)鐘滴答會通過IRQ0向系統(tǒng)發(fā)出一次時(shí)鐘中斷信號。通道1通常用于控制DMAC對RAM的刷新。通道2被連接到PC機(jī)的揚(yáng)聲器,以產(chǎn)生方波信號。下面我們重點(diǎn)關(guān)心通道0。每個(gè)通道都有一個(gè)遞減的計(jì)數(shù)器,8254PIT的輸入時(shí)鐘信號的頻率是1.193181MHZ,也即一秒鐘輸入1193181個(gè)時(shí)鐘周期。該數(shù)字在Linux內(nèi)核中被定義為:include/asm-i386/timex.h#defineCLOCK_TICK_RATE1193180每輸入一個(gè)時(shí)鐘周期其時(shí)間通道的計(jì)數(shù)器就自減1,一直減到0。因此對于通道0而言,當(dāng)他的計(jì)數(shù)器減到0時(shí),PIT就向系統(tǒng)產(chǎn)生一次時(shí)鐘中斷,表示一個(gè)時(shí)鐘滴答已經(jīng)過去了。該計(jì)數(shù)器為16bit,因此所能表示的最大值是65536,可以算出該定時(shí)器最慢一秒內(nèi)能發(fā)生的滴答數(shù)是:1193181/65536=18.206482。

PIT的I/O端口:40h通道0計(jì)數(shù)器可讀寫41h通道1計(jì)數(shù)器可讀寫42h通道2計(jì)數(shù)器可讀寫43h控制字只寫注意,因?yàn)镻ITI/O端口是8位的,而PIT相應(yīng)計(jì)數(shù)器是16位的,因此必須對PIT計(jì)數(shù)器進(jìn)行兩次讀寫才能得到完整的計(jì)數(shù)值。8254PIT的控制寄存器43h的格式如下:bit[7:6]為通道選擇位:

溫馨提示

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

最新文檔

評論

0/150

提交評論