標(biāo)題: 我對(duì)linux內(nèi)核的總結(jié)認(rèn)識(shí) [打印本頁]

作者: 51黑tt    時(shí)間: 2016-3-5 17:47
標(biāo)題: 我對(duì)linux內(nèi)核的總結(jié)認(rèn)識(shí)
第一次接觸linux是高三那時(shí),后來在大學(xué)里舍友T總的影響便開始了對(duì)linux的不斷追求與學(xué)習(xí)。讀萬卷書不如行萬里路,以前在學(xué)校里看了那么多書還不如工作中在代碼中煅練,當(dāng)然關(guān)鍵是找到個(gè)入門口點(diǎn),我選擇驅(qū)動(dòng)程序開始!下面總結(jié)和談下學(xué)習(xí)驅(qū)動(dòng)后對(duì)其的理解與認(rèn)識(shí)。



1.內(nèi)核是怎樣實(shí)現(xiàn)其管理的職能?

以前在學(xué)校時(shí)一直不能理解內(nèi)核是怎么做管理?比如內(nèi)核如何知道在什么時(shí)候?qū)Ω鱾(gè)進(jìn)程做調(diào)度,又在什么時(shí)候知道缺頁從而執(zhí)行內(nèi)存比如內(nèi)核如何知道在什么時(shí)候?qū)Ω鱾(gè)進(jìn)程做調(diào)度,又在什么時(shí)候知道缺頁從而執(zhí)行內(nèi)存管理的代碼,內(nèi)核為什么在會(huì)需要它管理的時(shí)候被喚醒,進(jìn)程在用戶態(tài)跑的好好的,又是誰喚醒內(nèi)核轉(zhuǎn)入核心態(tài)去check一下??jī)?nèi)核管理職能的實(shí)現(xiàn)一方面可以是通過中斷觸發(fā),這些中斷包括系統(tǒng)調(diào)用,硬件中斷;另一方面有一些內(nèi)核線程長(zhǎng)期運(yùn)行在內(nèi)核態(tài)。因?yàn)橄到y(tǒng)調(diào)用往往觸發(fā)相應(yīng)驅(qū)動(dòng)程序代碼的執(zhí)行,而驅(qū)動(dòng)程序本身包含大量可以導(dǎo)致進(jìn)程休眠的代碼,例如一個(gè)系統(tǒng)調(diào)用read把CPU從用戶態(tài)轉(zhuǎn)到核心態(tài),經(jīng)過虛擬文件系統(tǒng)VFS傳入到設(shè)備相關(guān)的驅(qū)動(dòng)程序中file_operations的真正實(shí)現(xiàn)函數(shù)read,這個(gè)系統(tǒng)調(diào)用可能引發(fā)內(nèi)核中很多管理模塊的執(zhí)行,假如驅(qū)動(dòng)中發(fā)現(xiàn)設(shè)備沒有可用的數(shù)據(jù)時(shí)對(duì)于阻塞型的調(diào)用,驅(qū)動(dòng)程序會(huì)把與其相關(guān)聯(lián)的用戶執(zhí)行線程掛起休眠,從而讓出了CPU實(shí)現(xiàn)了進(jìn)程調(diào)度器的調(diào)度。另外,一般來說CPU定時(shí)器會(huì)周期性地喚醒內(nèi)核讓其check一下,看一下有沒有東西需要它處理的(主要是引發(fā)了軟中斷的產(chǎn)生,進(jìn)而可能執(zhí)行一些軟中斷的任務(wù),稍后解釋什么是軟中斷)。這就是內(nèi)核的“心跳”,一般PC上會(huì)把這個(gè)心跳值HZ(每秒定時(shí)器中斷次數(shù))設(shè)置為100~1000,jiffies是開機(jī)累計(jì)心跳值。同樣,CPU外部的器件會(huì)產(chǎn)生大量的中斷,這樣使得內(nèi)核也知道了它將要干什么。最后,內(nèi)核線程kernel thread在內(nèi)核態(tài)周期性地執(zhí)行,例如磁盤高速緩存的刷新,網(wǎng)絡(luò)連接的維護(hù),頁面的換入換出等。



2.代碼執(zhí)行空間及其可見度

以前看一本書操作系統(tǒng)的書搞得好頭痛,x86上又是什么GDT,又是什么LDT,MMU的存在搞得內(nèi)存這塊非常的難懂。現(xiàn)在看來在區(qū)分用戶態(tài)和核心態(tài)的32位系統(tǒng)上,用戶進(jìn)程所能看到的空間僅僅分配給它的4G虛擬地址空間,用戶進(jìn)程要想通往內(nèi)核的唯一途徑是內(nèi)核事先定義的有限數(shù)目的“系統(tǒng)調(diào)用”。系統(tǒng)調(diào)用的實(shí)質(zhì)是該進(jìn)程把數(shù)據(jù)(包括中斷號(hào),系統(tǒng)調(diào)用的參數(shù))放進(jìn) CPU特定寄存器并向CPU發(fā)送一個(gè)異常。通往內(nèi)核并不意味著用戶進(jìn)程就能看到并且干預(yù)內(nèi)核空間,它能且僅能通過系統(tǒng)調(diào)用給定的接口參數(shù)向內(nèi)核申請(qǐng)服務(wù),這樣內(nèi)核會(huì)接手和代表用戶進(jìn)程并借用該用戶進(jìn)程的上下文繼續(xù)執(zhí)行(英文context的翻譯,是指程序計(jì)數(shù)器、棧和一組寄存器等),CPU轉(zhuǎn)入核心態(tài),內(nèi)核代碼就執(zhí)行該系統(tǒng)調(diào)用在內(nèi)核中的“實(shí)現(xiàn)部分”以滿足用戶進(jìn)程對(duì)數(shù)據(jù)操作的需要,就執(zhí)行路線上說,此時(shí)的內(nèi)核執(zhí)行處于“該用戶進(jìn)程上下文” 中,內(nèi)核能夠看到該用戶進(jìn)程的空間并且該執(zhí)行路線是與用戶進(jìn)程相關(guān),內(nèi)核訪問用戶空間的代碼隨體系結(jié)構(gòu)不同而有不同的實(shí)現(xiàn),而且需要經(jīng)過地址轉(zhuǎn)換。待內(nèi)核處理完系統(tǒng)調(diào)用返回后,則轉(zhuǎn)回用戶態(tài),用戶態(tài)進(jìn)程就在該系統(tǒng)調(diào)用返回繼續(xù)前行。在這種多任務(wù)的操作系統(tǒng)中,內(nèi)核代碼存在著多條執(zhí)行路線,所以內(nèi)核代碼非常講究代碼可重入性設(shè)計(jì)。在內(nèi)核中,中斷不與任何一個(gè)用戶進(jìn)程相關(guān),包括定時(shí)器中斷或者外圍硬件中斷和甚至“軟中斷”,即不是運(yùn)行在任何一個(gè)進(jìn)程的上下文中而是運(yùn)行在中斷上下文擁有自己的程序計(jì)數(shù)器、棧和一組寄存器;常常硬件中斷的發(fā)生并且被響應(yīng)必定意味著切換CPU上下文。中斷上下文不代表用戶進(jìn)程,所以中斷執(zhí)行例程不能訪問用戶空間的一切內(nèi)容。



3.驅(qū)動(dòng)程序是什么?及其與內(nèi)核的關(guān)系

驅(qū)動(dòng)程序本身就是內(nèi)核的一部分,從www.kernel.org下載回來的內(nèi)核代碼,單從代碼量來說驅(qū)動(dòng)程序超過占65%,當(dāng)然因?yàn)閮?nèi)核配置和條件編譯的關(guān)系,并不是所有的驅(qū)動(dòng)都會(huì)被選上。內(nèi)核中除掉驅(qū)動(dòng)程序以外的代碼是一個(gè)框架,該框架提供一個(gè)公有的屬性,不隨CPU體系架構(gòu)和具體硬件型號(hào)而變化,也是一個(gè)高度抽象模塊集,更是內(nèi)核的“基礎(chǔ)設(shè)施”,這個(gè)基礎(chǔ)設(shè)施向驅(qū)動(dòng)程序提供一些接口和定義一些標(biāo)準(zhǔn)。驅(qū)動(dòng)程序的設(shè)計(jì)要遵循內(nèi)核給定給驅(qū)動(dòng)程序的標(biāo)準(zhǔn)并使用內(nèi)核和接口,這樣就把操作具體硬件相關(guān)的工作交給了驅(qū)動(dòng)程序,抽象出更一般的模塊,提高了操作系統(tǒng)的可移植性,可擴(kuò)展性,和標(biāo)準(zhǔn)化。就像做填空題那樣,驅(qū)動(dòng)程序在內(nèi)核給定的空格上填好這個(gè)固定的空以使整個(gè)表達(dá)式是正確的。嚴(yán)格來說驅(qū)動(dòng)程序包括:CPU體系架構(gòu)驅(qū)動(dòng),各種各樣的硬件設(shè)施驅(qū)動(dòng)。一般的驅(qū)動(dòng)開發(fā)者其實(shí)工作的重點(diǎn)是除CPU外的設(shè)備的適配;贑PU體系架構(gòu)的實(shí)現(xiàn)依賴于具體的平臺(tái)如ARM,X86,SPARC,PPC,MIPS等,所以具體到平臺(tái)的實(shí)現(xiàn)部分有些是用匯編語言寫的,這些匯編因不同的體系結(jié)構(gòu)而不同(某種原因是C語言實(shí)現(xiàn)不了的操作,某些是基于采用匯編實(shí)現(xiàn)效率更高更安全)。比如在關(guān)中斷開斷的實(shí)現(xiàn)又或切換進(jìn)程上下文等操作采用匯編。除CPU外的設(shè)備一般C語言就完成了,因?yàn)榇蠖鄶?shù)是與操作寄存器和數(shù)據(jù)讀寫有關(guān)。這里應(yīng)該指明,現(xiàn)在的嵌入式芯片應(yīng)該稱之為SOC(System On Chip)更適合,而本文的CPU指的是處理器內(nèi)核比如ARM926EJ-S。設(shè)備驅(qū)動(dòng)程序是跟設(shè)備操作相關(guān)的系統(tǒng)調(diào)用的內(nèi)核實(shí)現(xiàn)版本。就是說對(duì)設(shè)備的操作(比如ioctl(fd,…))其在內(nèi)核的實(shí)現(xiàn)是由驅(qū)動(dòng)完成。所以驅(qū)動(dòng)要做的事情就是實(shí)現(xiàn)file_operations結(jié)構(gòu)的函數(shù)指針,安排中斷例程。當(dāng)然驅(qū)動(dòng)也有分層的,有些模塊純粹是一種軟件抽象。比如USB驅(qū)動(dòng)分層。驅(qū)動(dòng)程序是直接面對(duì)硬件,內(nèi)核通過驅(qū)動(dòng)與硬件交互。對(duì)內(nèi)核的核心來說驅(qū)動(dòng)屏蔽了硬件的實(shí)現(xiàn)細(xì)節(jié)。驅(qū)動(dòng)對(duì)硬件的操作集中表現(xiàn)在對(duì)寄存器的訪問及數(shù)據(jù)讀寫。



4.內(nèi)核線程,用戶線程,NPTL

以前的用戶態(tài)多線程的實(shí)現(xiàn)通過用戶態(tài)線程庫為其做調(diào)度與切換。想象一下,那時(shí)的多線程進(jìn)程,在內(nèi)核里只把該進(jìn)程看成一個(gè)執(zhí)行線程。多線間的切換調(diào)度是通達(dá)線程庫實(shí)現(xiàn),這樣效率是比較差,F(xiàn)在的2.6內(nèi)核NPTL線程庫其實(shí)是在1:1,就是說在用戶態(tài)進(jìn)程的線程在內(nèi)核里有對(duì)應(yīng)的代表線程。在“內(nèi)核”中 Linux并不區(qū)別線程與進(jìn)程,也就是說線程和進(jìn)程都用task_struct結(jié)構(gòu)表示,我想這句話一定會(huì)讓困惑于線程與進(jìn)程的朋友大為吃驚,不錯(cuò),在當(dāng)代2.6的linux內(nèi)核中的確如此,只不過,內(nèi)核可以讓某一些線程共享資源從而讓這些線程組給用戶空間看起來就像是一個(gè)進(jìn)程包含多個(gè)線程,這些共享的資源可以是打開的文件描述符,地址空間,信號(hào)處理程序和命名空間等等的任意組合。周期性運(yùn)行的內(nèi)核線程可以理解成在內(nèi)核中運(yùn)行的特殊進(jìn)程,它有自己的“進(jìn)程上下文”(借用調(diào)用它的用戶進(jìn)程的上下文),所以同樣被進(jìn)程調(diào)度程序調(diào)度,也可以睡眠——它和用戶進(jìn)程屬性何其相似,不同之處就在于內(nèi)核線程運(yùn)行于內(nèi)核空間,可訪問內(nèi)核數(shù)據(jù),運(yùn)行期間不能被搶占。傳統(tǒng)的Unix系統(tǒng)把一些重要的任務(wù)委托給周期性執(zhí)行的進(jìn)程,這些任務(wù)包括刷新磁盤高速緩存,交換出不用的頁面,維護(hù)網(wǎng)絡(luò)鏈接等等。事實(shí)上,以嚴(yán)格線性的方式執(zhí)行這些任務(wù)的確效率不高,如果把他們放在后臺(tái)調(diào)度,不管是對(duì)它們的函數(shù)還是對(duì)終端用戶進(jìn)程都能得到較好地響應(yīng)。因?yàn)橐恍┫到y(tǒng)進(jìn)程只運(yùn)行在內(nèi)核態(tài),現(xiàn)代操作系統(tǒng)把它們的函數(shù)委托給內(nèi)核線程(Kernel Thread),內(nèi)核線程不受不必要的用戶態(tài)上下文的拖累。在Linux中使用ps -eFT命令可以查看到所有內(nèi)核線程和用戶線程,所有有中括號(hào)[]的都是內(nèi)核線程,線程名后面跟著的數(shù)字代表該線程在哪個(gè)CPU上跑著,如果你的機(jī)器是SMP的話。



5.內(nèi)核信號(hào)量的設(shè)計(jì)與實(shí)現(xiàn),自旋鎖,與休眠隊(duì)列

暫時(shí)我的理解是自旋鎖其實(shí)就是while(鎖){}循環(huán)檢測(cè)鎖是否可用。這個(gè)過程CPU被死鎖在死循環(huán)中,可以想像這時(shí)除了等待鎖被釋放外啥也干不了。而內(nèi)核中信號(hào)量的設(shè)計(jì)里邊有自旋鎖和休眠方面操作。down(),up()及其變種版本,這兩個(gè)函數(shù)比較深?yuàn)W,只能理解到這里。呵呵



6.什么是軟中斷,tasklet, 中斷的bottom half(下半部分)

澄清一些概念,軟件中斷與軟中斷的區(qū)別(因?yàn)椴煌臅褂貌煌男g(shù)語可能導(dǎo)致混淆),軟件中斷大多指向CPU發(fā)送一個(gè)異常引發(fā)從用戶態(tài)到核心態(tài)的轉(zhuǎn)換,而軟中斷則是Linux的一個(gè)非常重要也挺復(fù)雜的一個(gè)機(jī)制那就是“延后執(zhí)行,但最晚不會(huì)晚于下一個(gè)定時(shí)器中斷的到來”,它并非一個(gè)真正意義上的中斷所以稱它為虛擬中斷。以前只知道定時(shí)器是可以給我們?cè)谝粋(gè)固定的時(shí)間后執(zhí)行定時(shí)器中斷例程來執(zhí)行我們的任務(wù),同時(shí),外圍硬件中斷也有很多,有些是很急也有不急的,像都不能在中斷例程里做太多操作與運(yùn)算,這樣中斷的處理的時(shí)間太長(zhǎng)從而影響了下一個(gè)中斷,但是環(huán)境客觀上又需要中斷例程處理很多數(shù)據(jù),比如網(wǎng)卡收到數(shù)據(jù)包發(fā)生中斷請(qǐng)求,此時(shí)中斷要做的事情是把數(shù)據(jù)復(fù)制和解析給用戶,這對(duì)中斷例程來說,他需要做的事情太多,但也不得不做;谶@種情況,內(nèi)核提供了一種設(shè)施,把中斷例程要做的事情分成兩半,上半部分和下半部分,上半部分只是做一些非常緊急和必要的操作然后退出,把其余的放在下半部在CPU不是那么緊急的或相對(duì)緩松的時(shí)刻來執(zhí)行,以致不影響下一個(gè)中斷。如果中斷例程任務(wù)不重大可不必分上半和下半。如需要分下半部分,那么下半部分怎樣的實(shí)現(xiàn)在CPU的一個(gè)比較寬松的環(huán)境里執(zhí)行呢?提供這種機(jī)制的是軟中斷!Linux的軟件中斷概念又是什么一回事?軟中斷(softirq)不象硬中斷那樣是由硬件中斷信號(hào)觸發(fā)執(zhí)行的,所以也不同于硬件中斷那樣時(shí)隨時(shí)都能夠被執(zhí)行,籠統(tǒng)來講,軟中斷會(huì)在內(nèi)核處理任務(wù)完畢后返回用戶級(jí)程序前得到處理機(jī)會(huì)。具體的講,有三個(gè)時(shí)刻它將被執(zhí)行(do_softirq()):硬件中斷操作完成后;系統(tǒng)調(diào)用返回時(shí);內(nèi)核調(diào)度程序中;(另外,內(nèi)核線程ksoftirqd周期執(zhí)行軟中斷)。從中可以看出軟中斷會(huì)緊隨硬中斷處理(好象狐假虎威),所以搶占內(nèi)核任務(wù)--至少在定時(shí)器中斷(時(shí)鐘中斷)后總有機(jī)會(huì)運(yùn)行一次。還要記得軟中斷可以在不同處器上并發(fā)執(zhí)行。在有對(duì)稱多處理器的機(jī)器上,那么兩個(gè)任務(wù)就可以真正的在臨界區(qū)中同時(shí)執(zhí)行了,這種類型被稱為真并發(fā)。相對(duì)而言在,單處理器上并發(fā)其實(shí)并不是真的同時(shí)發(fā)生,而是相互交錯(cuò)執(zhí)行,是偽并發(fā)。但它們都同樣會(huì)造成競(jìng)爭(zhēng)條件,而且也需要同樣的保護(hù)。軟中斷是很底層的機(jī)制,一般除了在網(wǎng)絡(luò)子系統(tǒng)和SCSI子系統(tǒng)這樣對(duì)性能要求很高以及要求并發(fā)處理的時(shí)候,才會(huì)選擇使用軟中斷。軟中斷雖然靈活性高和效率高,但是你自己必須處理復(fù)雜的同步處理(因?yàn)樗稍诙嗵幚砥魃喜l(fā)),所以通常都不直接使用,而是作為支持tasklet和bottom half的根本。需要說明的是,軟中斷的執(zhí)行也處于中斷上下文中,所以中斷上下文對(duì)它的限制是和硬中斷一樣的。Tasklet與定時(shí)器的不同其中之一在于tasklet是沒有一個(gè)固定的執(zhí)行延遲時(shí)間。



7.內(nèi)核編程與用戶態(tài)空間編程的差別

對(duì)于從事應(yīng)用程序開發(fā)來說,用戶空間的任務(wù)調(diào)度與同步之間的關(guān)系相對(duì)簡(jiǎn)單,無需過多考慮需要同步的原因。這一是因?yàn)樵谟脩艨臻g中各個(gè)進(jìn)程都擁有獨(dú)立的運(yùn)行空間,進(jìn)程內(nèi)部的數(shù)據(jù)對(duì)外不可見,所以各個(gè)進(jìn)程即使并發(fā)執(zhí)行也不會(huì)產(chǎn)生對(duì)數(shù)據(jù)訪問的競(jìng)爭(zhēng)。第二是因?yàn)橛脩艨臻g與內(nèi)核空間獨(dú)立,所以用戶進(jìn)程不會(huì)與內(nèi)核任務(wù)交錯(cuò)執(zhí)行,因此用戶進(jìn)程不存在與內(nèi)核任務(wù)并發(fā)的可能。以上兩個(gè)原因使得用戶同步僅僅需要在進(jìn)程間通訊和多線程編程時(shí)需要考慮。作為驅(qū)動(dòng)程序的一部分,內(nèi)核代碼的可重入設(shè)計(jì)需求非常迫切。其實(shí)還有很多。。。到時(shí)再寫。





歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1