北大青鳥linux學(xué)習(xí)內(nèi)核分析方法談_第1頁(yè)
北大青鳥linux學(xué)習(xí)內(nèi)核分析方法談_第2頁(yè)
北大青鳥linux學(xué)習(xí)內(nèi)核分析方法談_第3頁(yè)
北大青鳥linux學(xué)習(xí)內(nèi)核分析方法談_第4頁(yè)
北大青鳥linux學(xué)習(xí)內(nèi)核分析方法談_第5頁(yè)
已閱讀5頁(yè),還剩29頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

Linux內(nèi)核分析方法談作者:華技大學(xué)(hustyucc@163.netLinux的最大的好處之一就是它的源碼公開。同時(shí),公開的源碼也吸引著無(wú)數(shù)的電腦者和程序員;他們把解讀和分析Linux的源碼作為自己的最大,LinuxLinux系統(tǒng)作為自己對(duì)計(jì)算機(jī)技術(shù)追求的最大目標(biāo)。Linux內(nèi)核源碼是很具的,特別是當(dāng)你弄懂了一個(gè)分析了好久都沒(méi)搞懂的的份量和作用,以及一些宏觀設(shè)計(jì)的方法和技巧:Linux件相關(guān)的部分,和可移植的部分;再例如,Linux內(nèi)核代碼的模塊獨(dú)立性。。。的碼和。。至分分一碼你會(huì)刻地體會(huì)到,什么樣的代碼才是一個(gè)專業(yè)的程序員寫的,什么樣的代碼是一個(gè)業(yè)余者寫的。而這一點(diǎn)是任何沒(méi)有真正分析過(guò)標(biāo)準(zhǔn)代碼的人都無(wú)法體會(huì)到的。很需要毅力的事;在缺乏指導(dǎo)和交流的情況下,尤其如此。只有方法正確,才能事半功倍。正是基于這種考慮,作者希望通過(guò)此文能給大家一些借鑒和啟迪。i3862.2.5Linuxusrsrclinux方法之一、從何入手要分析Linux內(nèi)核源碼,首先必須找到各個(gè)模塊的位置,也即要弄懂源碼的文件組織形式。雖然對(duì)于有經(jīng)驗(yàn)的高手而言,這個(gè)不是很難;但對(duì)于很多初級(jí)的Linux者,和那些對(duì)源碼分析很有但接觸不多的人來(lái)說(shuō),這還是很有必要的。1。Linux源程序通常都安裝在/usr/src/linux,而且它有一個(gè)非常簡(jiǎn)單的編號(hào)約定:任何偶數(shù)的(的二個(gè)數(shù)為偶數(shù),例如2.0.30)都是一個(gè)穩(wěn)定地的,而任何奇數(shù)的(例如2.1.42)都是一個(gè)開發(fā)中的。2。源程序的文件按樹形結(jié)構(gòu)進(jìn)行組織,在源程序樹的最上層,/usr/src/linux下有這樣一 和文件COPYING: MAINTAINERS:人員列表,對(duì)當(dāng)前版本的內(nèi)核各部分都有誰(shuí)負(fù)責(zé)Makefile:第一Makefile文件。用來(lái)組織內(nèi)核的各模塊,記錄了個(gè)模塊間的相互這間的聯(lián)系和依托關(guān)系,編譯時(shí)使用;仔細(xì)閱讀各子下的Makefile文件ReadMe:及其編譯配置方法簡(jiǎn)單介紹Arch/:arch 都代表一種支持的體系結(jié)構(gòu),例如i386就是關(guān)于incpu及與之相兼容體系結(jié)構(gòu) 。PC機(jī)一般都基于此 Include/:include子 頭文件在include/linux子 下,而include/scsi 則是有關(guān)scsi設(shè)備的頭文件 Init/:這個(gè) 文件main.c和Version.c,這是研究如何工作的好的起點(diǎn)之一。 內(nèi)存的分配和釋放等;而和體系結(jié)構(gòu)相關(guān)的內(nèi)存管理代碼則位于arch/*/mm/,例如 其中最重要的文件當(dāng)屬sched.c;同樣,和體系結(jié)構(gòu)相關(guān)的代碼在arch/*/kernel中Drivers/:放置系統(tǒng)所有的設(shè)備驅(qū)動(dòng)程序;每種驅(qū)動(dòng)程序又各占用一個(gè)子 它不僅初始化硬盤,也初始化網(wǎng)絡(luò),因?yàn)榘惭bnfs文件系統(tǒng)的時(shí)候需要網(wǎng)絡(luò);ation/:文檔 English的,看看應(yīng)該有用的哦;Fs/:所有的文件系統(tǒng)代碼和各種類型的文件操作代碼,它的每一個(gè)子 個(gè)文件系統(tǒng),例如fat和ext2;Ipc/:這 包含的進(jìn)程間通訊的代碼Lib/:放置的庫(kù)代碼Net/:與網(wǎng)絡(luò)相關(guān)的代碼Modules/:模塊文 Scripts/:描述文件,,用于對(duì)的配置一般,在每個(gè)子下,都有一個(gè)MakefileReadme對(duì)Linux內(nèi)核源碼的分析,有幾個(gè)很好的點(diǎn):一個(gè)就是系統(tǒng)的引導(dǎo)和初始化,即從機(jī)器加電到系統(tǒng)的運(yùn)行;另外一個(gè)就是系統(tǒng)調(diào)用,系統(tǒng)調(diào)用是用戶程序或操作調(diào)用核心所提供的功能的接口。對(duì)于那些對(duì)硬件比較熟悉的者,從系統(tǒng)的引導(dǎo)入手進(jìn)行分析,可能來(lái)的容易一些;而從系統(tǒng)調(diào)用下口,則可能更合適于那些在dos或Uinx、Linux下有過(guò)C編程經(jīng)驗(yàn)的高手。這兩點(diǎn),在后面還將介紹到。方法之二、以程序流程為線索,一線串珠從表面上看,Linux的源碼就象一團(tuán)扎亂無(wú)章的亂麻,其實(shí)它是得有條有理I、系統(tǒng)的引導(dǎo)bootsect-loaderlinuxbootsect-loader/Arch/i386/boot/bootsect.S一、幾個(gè)相關(guān)文件:<1.><2.><3.> 二、引導(dǎo)過(guò)程分析:對(duì)于Inx86PC,開啟電源后,機(jī)器就會(huì)開始執(zhí)行ROMBIOS的一系列系統(tǒng)測(cè)試動(dòng)作,包括檢查RAM,keyboard,顯示器,軟硬磁盤等等。執(zhí)行完bios的系統(tǒng)測(cè)試之后,緊接著控制權(quán)會(huì)轉(zhuǎn)移ROM中的啟動(dòng)程序(ROMbootstraproutine);這個(gè)程序會(huì)將磁盤上的第00(bootsectorMBR<MasterBootRecord處)讀入內(nèi)存中,并放到自0x07C0:0x0000開始的512個(gè)字節(jié)處;然后處理機(jī)將跳到此處開MBRCS:IP0x07C0:0x0000理機(jī)運(yùn)行在與8086相兼容的實(shí)模式下。如果要用bootsect-loader進(jìn)行系統(tǒng)引導(dǎo),則必須把bootsect.S編譯連接后對(duì)應(yīng)的MBRROMBIOSbootsect.Sbootsect;,bootsectBootsect接管機(jī)器控制權(quán)后,將依次進(jìn)行以下一些動(dòng)作: go,INITSEG”后的那條指令“go:movdi,#0x4000-12”;之后,繼續(xù)執(zhí)行bootsect的剩BOOTSEG= biosMBRINITSEG=0x9000 SETUPSEG=0x9020 裝入Setup.S的段址 對(duì)于這些常量可參見(jiàn)/include/asm/boot.h0x9000:0x4000-120x9000:0x4000的一十二個(gè)預(yù)留字節(jié)中建立新的磁盤biosbios建立的磁盤參數(shù)表妨礙磁盤的最高性能發(fā)揮,所以,設(shè)計(jì)者就在bios建立的磁盤參數(shù)表的并把參數(shù)表的位置由原來(lái)的0x0000:0x00780x9000:0x4000-12;且修改老的磁盤參load_setup0x13200x9000:0x02002048個(gè)字節(jié);而這四個(gè)扇區(qū)的內(nèi)容即是/arch/i386/boot/setup.S編譯連接后對(duì)應(yīng)的二進(jìn)制代碼; 要用bootsect-loader進(jìn)行系統(tǒng)引導(dǎo),不僅必須把bootsect.S編譯連接后對(duì)應(yīng)的二進(jìn)制代碼置于MBR,而且還得把setup.S編譯連接后對(duì)應(yīng)的二進(jìn)制代碼置于緊跟MBR后的連續(xù)的四個(gè)扇區(qū)中;當(dāng)然,由于setup.S對(duì)應(yīng)的可執(zhí)行碼是由bootsect裝載的,所以,在我們的這個(gè)項(xiàng)目中可以通過(guò)修改bootsect來(lái)根據(jù)需要隨意地放置setup.S對(duì)應(yīng)的可執(zhí)行最后跳轉(zhuǎn)到0x9000:0x0200,即setup.S對(duì)應(yīng)的可執(zhí)行碼的,將機(jī)器控制權(quán)轉(zhuǎn)交setup.S;整個(gè)bootsect代碼運(yùn)行完畢;三 引導(dǎo)過(guò)程執(zhí)行完后的內(nèi)存印象圖II、實(shí)模式下的初始化一些處理。在內(nèi)核源碼中對(duì)應(yīng)的程序是/Arch/i386/boot/setup.S;以下部分主要是針及建立的基礎(chǔ)。一、個(gè)其它相關(guān)文件: /include/ extendedmemory大小,并存入9000:0002LinuxLinux實(shí)模式下的初始化流程圖為1000,正確的段址還必須加setup部輸出“Nosetupsignaturefound是輸出“Wrongloader:givinghd0hda1Hda1Hda1存在Linux實(shí)模式下的初始化流程圖二,關(guān)中斷,BIG是以SYSSEG與INITSEG間的4KB作為緩沖取每次4K,將系統(tǒng)搬到0x0100:0000處idt為空,gdt0x9xxxx,256檢查自己是否位于SETUPSEG處,inidt為空,gdt0x9xxxx,256檢查自己是否位于SETUPSEG處,INITSEG(9000:0000)段參(參見(jiàn)2extendedmem22112221122224442622220x0034--APMBIOS2BIOScode2BIOSentry4BIOS16bitcode2BIOSdata22BIOScodeseg4BIOSdataseg2hd0hd0PS/2device1*注Include/linux/tty.hCL_MAGICandCL_OFFSET②Include/linux/tty.hunsignedchar /*0x2cunsignedchar /*0x2d0APMIII、保護(hù)模式下的初始化程中系統(tǒng)所做的一些處理。保護(hù)模式下的初始化在內(nèi)核源碼中對(duì)應(yīng)的程序是 pressed/head.S/Arch/i386/KERNEL/head.S;以下部分主要一、幾個(gè)相關(guān)文件: /include/ /include/asm-二、保護(hù)模式下的初始化過(guò)程分析:/Arch/i386/KERNEL/head.S/Arch/i386/KERNEL/head.S流程圖用KERNEL_DS此時(shí) 只定義了2個(gè)頁(yè)表項(xiàng) 將BSS第0項(xiàng)和第768項(xiàng),此兩項(xiàng)都對(duì)應(yīng)同一個(gè)頁(yè)表0x00102,同時(shí),址的0—4M,即在0—4M,物理 的第768 將BSS,服務(wù)程序初始化臨時(shí)idt,共256BSS,服務(wù)程序初始化臨時(shí)idt,共256 2K,用pushl INITSEG段的參數(shù)參見(jiàn)empty_zero_page后 ==

為保護(hù)虛擬/Arch/i386/KERNEL/head.S/Arch/i386/KERNEL/head.S流程圖CPU信息被放在一個(gè)boot_cpu_datacpuinfo_x86中,參見(jiàn)gdt到了一個(gè)只含兩個(gè)有效系統(tǒng)段的Gdt;此處重新建立gdt,新的gdt位于0x106000,gdt到8byte置了兩個(gè)系統(tǒng)段和4G小,還設(shè)4APM只需start_kernelstart_kernel二、 流程用KERNEL_DS用pushl 將BSS將BSSpress_kernelpress_kernel是 compressed/MISC.Chead.S

從頁(yè)和pg0表可以看出,0—4M理內(nèi)存被用作系統(tǒng)區(qū),它被映射到系統(tǒng)段線性空間的0—4M和3G—3G+4M;即系統(tǒng)可以通過(guò)這兩個(gè)實(shí)際的0—4M物本來(lái)在實(shí)模式下初始化時(shí)已經(jīng)建立了全局描述符表gdt,而此處重新建立全局描jxxnfjxxnb;gdt是建立在實(shí)地址方式下的,而現(xiàn)在則是在啟用保護(hù)虛擬地址方式之后建立的,也即現(xiàn)在的gdt是建立在邏輯地址(即線性地址)上的;實(shí)實(shí)模式到386保護(hù)模式流程圖386386必要的;又因?yàn)樵?86保護(hù)模式下gdt和idt是建立在邏輯地址(線性地址)上的,所以 Linux系統(tǒng)的初始化過(guò)程的分析可以看出,以程序執(zhí)行流程為線索、一方法之三、以數(shù)據(jù)結(jié)構(gòu)為基點(diǎn),觸類旁通結(jié)構(gòu)化程序設(shè)計(jì)思想認(rèn)為:程序=Linux序漸進(jìn)的思想,在這我就以Linux對(duì)中斷機(jī)制的處理來(lái)介紹這種方法。首先,必須的是:在此處,中斷指廣義的中斷概義,它指所有通過(guò)idt進(jìn)行的控制轉(zhuǎn)移的機(jī)制和處理;它覆蓋以下幾個(gè)常用的概義:中斷、異常、可中斷、不可中斷、硬中斷、軟中斷???I、硬件提供的中斷機(jī)制和約定一.中斷向量尋址中斷向量在保護(hù)模式下的實(shí)現(xiàn)機(jī)制是中斷描述符表idt,idtidtr確定,idtr48的寄32idt16idt的界限(通常為idt256中斷描述符,對(duì)應(yīng)256向量;每個(gè)中斷描述符8SelectorOffset(15?0)0SelectorOffset(15?0)2-P0x0E0x00Offset(31?16)15,1413,12??8,7?P0x0E0x00Offset(31?16)4-6-注:P=1,該描述符有效,P=0,無(wú)效,使用則觸發(fā)異常DPL,00-11,對(duì)應(yīng)四個(gè)級(jí)(00最高當(dāng)中斷是由低級(jí)轉(zhuǎn)到高級(jí)(即當(dāng)前級(jí)CPL>DPL)時(shí),將進(jìn)行堆棧的轉(zhuǎn)SS,ESP,EFLAGS,CS,EIP;中斷返回過(guò)程為一逆過(guò)程;????服務(wù)程序????二.異常處理機(jī)制:in公司保留0-31號(hào)中斷向量用來(lái)處理異常:當(dāng)產(chǎn)生一個(gè)異常時(shí),處理機(jī)就會(huì)自動(dòng)把控制轉(zhuǎn)移到相應(yīng)的處理程序的,異常的處理程序由操作系統(tǒng)提供,中斷表一、中斷向量和異常對(duì)應(yīng)表0123單字節(jié),int456789三.可編程中斷控制器8259A:接受外部的中斷信號(hào);對(duì)于中斷,cpu:NMIINTR可通過(guò)直接設(shè)置中斷位來(lái),它可用來(lái)接受外部中斷信號(hào),但只有一IRQ(中斷請(qǐng)求)管腳上首先由中斷控制器處理。中斷控制器可以響應(yīng)多個(gè)中斷輸入,它的輸出連接到CPUINTINT管腳,通知處理器產(chǎn)生了中斷。如果CPU這時(shí)可以處理中斷,CPU會(huì)通過(guò)INTA(中斷確認(rèn))管腳上的信號(hào)通知中斷控制器已接受中斷,這時(shí),中斷控制器可將一個(gè)8位數(shù)8位數(shù)據(jù)也稱為中斷向量號(hào),CPU依據(jù)中斷向量號(hào)和中斷描起來(lái),從屬中斷控制器的輸出連接到了主中斷控制器的第3個(gè)中斷信號(hào)輸入,這樣,該15i386PC中各中斷輸入管腳的下初始化時(shí)把其設(shè)在0x20-0x2F,對(duì)此下面還將具體說(shuō)明。從中控制從中控制主中控制IRQ0(時(shí)鐘IRQ1(鍵盤IRQ3(tty2)IRQ4(ttyIRQ5(XTWinchester)IRQ6(軟驅(qū))IRQ7 IRQ8(實(shí)時(shí)時(shí)鐘IRQ9(重定向的IRQ2)IRQ10IRQIRQIRQ13(FPU異常)IRQ14(ATWinchester)IRQ15II、Linux的中斷處理硬件中斷機(jī)制提供了256個(gè),即idt中包含的256個(gè)中斷描述符(對(duì)應(yīng)而0-31號(hào)中斷向量被in公司保留用來(lái)處理異常,不能另作它用。對(duì)自動(dòng)把控制轉(zhuǎn)移到相應(yīng)的處理程序的,運(yùn)行相應(yīng)的處理程序;而事實(shí)上,對(duì)于這32個(gè)處理異常的中斷向量,此版本(2.2.5)Linux0-17序,其對(duì)應(yīng)處理程序參見(jiàn)表一、中斷向量和異常對(duì)應(yīng)表;也就是說(shuō),17-31號(hào)中斷224個(gè)中斷向量又是怎么分配的呢?在此版本(2.2.5)的Linux中,除了0x80(SYSCALL_VECTOR)用作系統(tǒng)調(diào)用總之外,其他都用在外部硬件中斷源上,其中包括可編8259A15irq;事實(shí)上,當(dāng)沒(méi)有定義CONFIG_X86_IO_APIC時(shí),其一.相關(guān)數(shù)據(jù)結(jié)構(gòu)中斷服務(wù)例程的。(詳細(xì)描述參見(jiàn)圖一、中斷描述符格式)與硬中斷相關(guān)數(shù)據(jù)結(jié)構(gòu):中的structhw_interrupt_type{constchar*typename;void(*startup)(unsignedintirq);void(*shutdown)(unsignedintvoid(*handle)(unsignedintirq,structpt_regs*regs);void(*enable)(unsignedintirq);void(*disable)(unsignedint中的typedefstructunsignedint IRQ_DISABLEDstructhw_interrupt_type*handler;/* functions*/structirqaction /*IRQactionlistunsignedint }structirqactionvoid(*handler)(int,void*,structpt_regs*);unsignedlongflags;unsignedlongmask;constchar*name;void*dev_id;structirqaction…...…...……

irq_desc[

各結(jié)構(gòu)成員詳述如下:flags:取值只有SA_INTERRUPT(中斷可嵌套SA_SAMPLE_RANDO(這個(gè)中斷是源于物理隨機(jī)性的SA_SHIRQ(這個(gè)IRQ和其它structirqaction共享SPARC64的移植版本中要有關(guān)軟盤的信息時(shí)才會(huì)使用它。name:產(chǎn)生中斷的硬件設(shè)備的名字。因?yàn)椴恢挂粋€(gè)硬件可以共 IRQdev_id:標(biāo)識(shí)硬件類型的一個(gè)唯一的ID。Linux支持的所有硬件設(shè)備的每一種類next:如果IRQ是共享的,那么這就是指向隊(duì)列中下一structirqaction結(jié)構(gòu)的指針。通常情況下,IRQ不是共享的,因此這個(gè)成員就為空。typename:控制器的名startup:允許從給定的控制器的IRQ所產(chǎn)生的shutdown:從給定的控制器的IRQ所產(chǎn)生的handle:根據(jù)提供給該函數(shù)的IRQ,處理唯一的中enabledisable這兩個(gè)函數(shù)基本上和startup和shutdown相同另外一個(gè)數(shù)據(jù)結(jié)構(gòu)是irq_desc_tstatus:一個(gè)整數(shù)。代表IRQ的狀態(tài):IRQ是否被了,有關(guān)IRQ的設(shè)備當(dāng)前handlerhw_interrupt_typeaction:指irqaction結(jié)構(gòu)組成的隊(duì)列的頭。正常情況下每個(gè)IRQ只有一個(gè)操作,因此列表的正常長(zhǎng)度是1(或者0。但是,如果IRQ被兩個(gè)或者多個(gè)設(shè)備組把每一個(gè)IRQirq_desc_t中的其它信息。與Bottom_half相關(guān)的數(shù)據(jù)結(jié)構(gòu):

0

bh_mask_count:計(jì)數(shù)器。對(duì)每個(gè)enable/disable請(qǐng)求嵌套對(duì)進(jìn)行計(jì)數(shù)。這些請(qǐng)求通過(guò)調(diào)用enable_bh和disable_bh實(shí)現(xiàn)。每個(gè)請(qǐng)求都增加計(jì)數(shù)器;每個(gè)使能請(qǐng)求都減小計(jì)數(shù)器。當(dāng)計(jì)數(shù)器達(dá)到0時(shí),所有未完成的語(yǔ)句都已經(jīng)被使能特別是如果位與運(yùn)算的結(jié)果是0,就沒(méi)有下半部分需要運(yùn)行。 bh_base——是一組簡(jiǎn)單的指向下半部分處理函數(shù)bh_base代表的指針數(shù)組中可包含32個(gè)不同的底半處理程序。bh_mask和bh_activebh_maskN位為1,則說(shuō)明bh_base數(shù)組的第N個(gè)元素包含某個(gè)底半處理過(guò)程的地址;如果bh_active的第N位為1,則說(shuō)明必須由調(diào)度程序在適當(dāng)?shù)臅r(shí)候調(diào)用第N個(gè)底半處理二.向量的設(shè)置和相關(guān)數(shù)據(jù)的初始化:控制轉(zhuǎn)到對(duì)應(yīng)的中斷服務(wù)例程。(Arch/i386/boot/setup.S容可參見(jiàn)實(shí)模式下的初始化部分)在保護(hù)模式下的初始化過(guò)程中,設(shè)置并初始化idt,共256個(gè),Arch/i386/KERNEL/head.S)在系統(tǒng)初始化完成后運(yùn)行的第一個(gè)內(nèi)核程序asmlinkagevoid start_kernel(void)(源碼在文件init/main.c中)中,通過(guò)調(diào)用void arch/i386/kernel/traps.c在同一個(gè)函數(shù)void inittrap_init(void)中,通過(guò)調(diào)用函數(shù)set_system_gate(SYSCALL_VECTOR,&system_call);把系統(tǒng)調(diào)用總控程序的入口掛在中斷0x80上。其中SYSCALL_VECTOR是定義在linux/arch/i386/kernel/irq.h中的一個(gè)常量0x80;而system_call即為中斷總控程序的地址;中斷總控程序用匯編語(yǔ)言定義在arch/i386/kernel/entry.S中。(相關(guān)內(nèi)容可參見(jiàn)詳解系統(tǒng)調(diào)用部分)在系統(tǒng)初始化完成后運(yùn)行的第一個(gè)內(nèi)核程序asmlinkagevoidinitstart_kernel(void)(源碼在文件init/main.c中)中,通過(guò)調(diào)用voidarch/i386/kernel/IRQ.c中;)interrupt[i](i1-223),arch/i386/kernel/IRQ.c(這些定義interrupt[i]的宏,全部定義在文件arch/i386/kernel/IRQ.c和各以interrupt[i]為的代碼,在進(jìn)行一些簡(jiǎn)單的處理后,最后arch/i386/kernel/IRQ.carch/i386/kernel/IRQ.HIrqaction三.Bottom_half處理機(jī)制在此版本(2.2.5)的Linux中,中斷處理程序從概念上被分為上半部分(tophalf)和下半部分(bottomhalf;在中斷發(fā)生時(shí)上半部分的處理過(guò)程立即執(zhí)行,但是下半部分(如果有的話)卻推遲執(zhí)行。內(nèi)核把上半部分和下半部分作為獨(dú)立的函數(shù)來(lái)處理,上半部分決定其相關(guān)的下半部分是否需要執(zhí)行。必須立即執(zhí)行的部分必須位于上半Linux內(nèi)核定義了兩種類型的中而快速中斷則不能。因此,當(dāng)處理快速中斷時(shí),如果有其它中斷到達(dá)——不管是快速中斷還是慢速中斷——它們都必須等待。為了盡可能快地處理這些其它的中斷,內(nèi)核就需要盡可能地將處理延下半部分執(zhí)行。另外一個(gè)原因是,當(dāng)內(nèi)核執(zhí)行上半部分時(shí),正在服務(wù)的這個(gè)特殊IRQ將會(huì)被可編程中斷控制器,于是,連接在同一個(gè)IRQ上的其它設(shè)備就只有等到該該中斷處理被處理完畢才能發(fā)出IRQ請(qǐng)求。而采用Bottom_half機(jī)制后,bh_maskbh_active1(do_botoom_half)(也可能在其他地方)決定必須執(zhí)行對(duì)應(yīng)的半部分,那么可以通過(guò)設(shè)置bh_active的對(duì)應(yīng)位,來(lái)指明下半部分必須執(zhí)行。當(dāng)然,如果bh_active的對(duì)應(yīng)位被置位,也不一定會(huì)馬上執(zhí)行下半部分,因?yàn)檫€必須具備另外兩個(gè)條件:首先是bh_mask的相應(yīng)位也必須被那么內(nèi)核就簡(jiǎn)單地保持這個(gè)標(biāo)記;當(dāng)情況允許的時(shí)候,內(nèi)核就對(duì)它進(jìn)行處理。如果在內(nèi)核有機(jī)會(huì)運(yùn)行其下半部分之前給定的設(shè)備就已經(jīng)發(fā)生了100次中斷,那么內(nèi)核的上半部bh_base數(shù)組的索引是靜態(tài)定義的,定時(shí)器底半處理過(guò)程的地址保存在第0個(gè)元素中,控制臺(tái)底半處理過(guò)程的地址保存在第1個(gè)元素中,等等。當(dāng)bh_mask和bh_activeNN調(diào)度程序從第0個(gè)元素開始依次檢查每個(gè)底半處理過(guò)程,因此,第0個(gè)底半處理過(guò)程31二列出了內(nèi)核中通用的底半處理過(guò)程。表二、 中通用的底半處理過(guò)程(定時(shí)器 CONSOLE_BH(控制臺(tái) 該處理過(guò)程用來(lái)處理控制臺(tái)消息TQUEUE_BH(TTY

tty 表明需要進(jìn)行底半處理。為了通知內(nèi)核,只需將bh_active的相應(yīng)數(shù)據(jù)位置為1。immediateIMMEDIATEbh_active81。在每個(gè)系統(tǒng)調(diào)用結(jié)束并返回調(diào)用進(jìn)程之前,調(diào)度程序要檢驗(yàn)bh_active中的每個(gè)位,如果有任何相應(yīng)為被清除。bh_active中的置位只是暫時(shí)的,在兩次調(diào)用調(diào)度程序之間bh_active的值才有意義,如果bh_active中沒(méi)有置位,則不需要調(diào)用任何底半處四.中斷處理全過(guò)程由前面的分析可知,對(duì)于0-31號(hào)中斷向量,被保留用來(lái)處理異常;0x80中斷向量用來(lái)作為系統(tǒng)調(diào)用的總點(diǎn);而其他中斷向量,則用來(lái)處理外部設(shè)備中斷;這一、異常的處理全過(guò)程常時(shí),處理機(jī)就會(huì)自動(dòng)把控制轉(zhuǎn)移到相應(yīng)的處理程序的二 中斷的處理全過(guò)CPUCPUret_from_intrLinux方法之四、以功能為中心,各個(gè)擊破以功能為中心、各個(gè)擊破,就是指從這五個(gè)功能入手,通過(guò)源碼分析,找出在這五個(gè)功能部件中,系統(tǒng)調(diào)用是用戶程序或操作調(diào)用所提供的功能的接口;也是分析Linux內(nèi)核源碼幾個(gè)很好的點(diǎn)之一。對(duì)于那些在dos或Uinx、Linux下有過(guò)C編程經(jīng)驗(yàn)的高手尤其如此。又由于系統(tǒng)調(diào)用相對(duì)其它功能而言,較為簡(jiǎn)單,所以,I、系統(tǒng)調(diào)用的初始化設(shè)置和相關(guān)數(shù)據(jù)結(jié)構(gòu)與系統(tǒng)調(diào)用相關(guān)的內(nèi)容主要有:系統(tǒng)調(diào)用總控程序,系統(tǒng)調(diào)用向量表sys_call_table以及各系統(tǒng)調(diào)用服務(wù)程序。下面將對(duì)此一一介紹:保護(hù)模式下的初始化過(guò)程中,設(shè)置并初始化idt,共256個(gè),服務(wù)start_kernel調(diào)用trap_init函數(shù),把各自陷和中斷服務(wù)程序的地址設(shè)置到idt表中;掛在中斷0x80上。其中: init/main.c中arch/i386/kernel/traps.c中

initstart_kernel(void)inittrap_init(void),定義在調(diào)用原型為set_system_gate(SYSCALL_VECTOR,&system_call);的一個(gè)常量0x80;用匯編語(yǔ)言定義在arch/i386/kernel/entry.S中。(其它相關(guān)內(nèi)容可參見(jiàn)中斷和中斷處理部分系統(tǒng)調(diào)用向量表sys_call_table,是一個(gè)含有NR_syscalls=256個(gè) 定義在include/linux/sys.h中。asmlinkageintsys_time(int*tloc)kernel\time.ckernel\sys.c中也有不少服務(wù)程序;II、系統(tǒng)調(diào)用過(guò)程我們知道,系統(tǒng)調(diào)用是用戶程序或操作調(diào)用所提供的功能的接口;所以系統(tǒng)Linux…...系統(tǒng)下…...系統(tǒng)下一……保護(hù)現(xiàn)①下一語(yǔ)……恢復(fù)現(xiàn)

系統(tǒng)調(diào)用 地址地址

服務(wù)………………服務(wù)程……用戶程序系統(tǒng)調(diào)用總控程序(system_call)各個(gè)服務(wù)程序可見(jiàn),系統(tǒng)調(diào)用的進(jìn)入課分為“用戶程序系統(tǒng)調(diào)用總控程和“系統(tǒng)調(diào)用總控程序各個(gè)服務(wù)程序”“用戶程序系統(tǒng)調(diào)用總控程序”的實(shí)現(xiàn):面已經(jīng),Linux的系統(tǒng)調(diào)用使用第0x80號(hào)中斷向量項(xiàng)作為總 0x80int0x80C庫(kù)中,int0x80。至于中斷的進(jìn)入的詳細(xì)過(guò)程可參見(jiàn)前面的“中斷和中斷處理”部分。“系統(tǒng)調(diào)用各個(gè)服務(wù)程序?qū)崿F(xiàn):在系統(tǒng)調(diào)用總控程序中通過(guò)語(yǔ)句“call*SYMBOL_NAME(sys_call_table)(,%eax,4X),可以忽略。當(dāng)系統(tǒng)調(diào)用總控程序執(zhí)行到此語(yǔ)句時(shí),eaxsys_call_table編號(hào)(關(guān)于系統(tǒng)調(diào)用的編號(hào)說(shuō)明在/linux/include/asm/unistd.h中。又因?yàn)橄到y(tǒng)調(diào)用的地址。所以此call語(yǔ)句就相當(dāng)于直接調(diào)用對(duì)應(yīng)的系統(tǒng)調(diào)用服務(wù)程序。此標(biāo)志是一個(gè)定義在/include/linux/linkage.h中的一個(gè)宏:#ifdefinedi386&&(GNUC>2||GNUC_MINOR>7)#defineasmlinkageCPP_ASMLINKAGEattribute((regparm(0)))#defineasmlinkageCPP_ASMLINKAGE其中涉及到了gcc的一些約定,總之,這個(gè)標(biāo)志它可以告訴編譯器該函數(shù)不需要從 = = = = = = = = = =0x24 = = =在進(jìn)入系統(tǒng)調(diào)用總控程序前,用戶按照以上的對(duì)應(yīng)順序?qū)?shù)放到對(duì)應(yīng)寄存器于系統(tǒng)調(diào)用服務(wù)程序而言,參數(shù)就可以直接從總控程序壓入的堆棧中復(fù)得;對(duì)參數(shù)的的服務(wù)程序都是定義在/usr/src/linux/kernel/sys.c中的同一個(gè)函數(shù):asmlinkageint{return-}Nr17Nr31,Nr32,Nr35,44,Nr53,Nr56,Nr58,Nr用于將要擴(kuò)展的系統(tǒng)調(diào)用,如 Nr137,Nr188,NrIII、系統(tǒng)調(diào)用總控程序(system_call)系統(tǒng)調(diào)用總控程序(system系

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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)論