?? (ldd) ch01-linux內(nèi)核簡(jiǎn)介(轉(zhuǎn)載).txt
字號(hào):
(LDD) Ch01-Linux內(nèi)核簡(jiǎn)介(轉(zhuǎn)載)
第1章 Linux內(nèi)核簡(jiǎn)介
世界各地都有人在鉆研Linux內(nèi)核,大多是在寫設(shè)備驅(qū)動(dòng)程序。盡管每個(gè)驅(qū)動(dòng)程序都不一
樣,而且你還要知道自己設(shè)備的特殊性,但是這些設(shè)備驅(qū)動(dòng)程序的許多原則和基本技術(shù)
技巧都是一樣的。通過(guò)本書,可以學(xué)會(huì)寫自己的設(shè)備驅(qū)動(dòng)程序,并且可以鉆研內(nèi)核的相
關(guān)部分。本書涉及到的是設(shè)備無(wú)關(guān)編程技巧,不會(huì)將例子跟特殊設(shè)備綁定在一起。
本章沒有實(shí)際編寫代碼。但我要介紹一些關(guān)于Linux內(nèi)核的背景概念,這樣到我們稍后開
始介紹實(shí)際編程時(shí),就很順利了。
當(dāng)你學(xué)習(xí)編寫驅(qū)動(dòng)程序的時(shí)候,你也會(huì)發(fā)現(xiàn)很多關(guān)于Linux內(nèi)核的知識(shí),這對(duì)理解你機(jī)器
怎么工作很有幫助,并且還可以知道為什么你的機(jī)器沒有希望的那么快,或者為什么不
按照你象要它做的那樣做。我們會(huì)逐漸介紹一些新概念,先從簡(jiǎn)單的驅(qū)動(dòng)程序開始,每
介紹一些新概念都會(huì)看到相關(guān)例子代碼,這些代碼都不需要特殊硬件。
介紹一些新概念都會(huì)看到相關(guān)例子代碼,這些代碼都不需要特殊硬件。
驅(qū)動(dòng)程序作者的作用
作為一個(gè)程序員,你可以選擇自己的驅(qū)動(dòng)程序,在編程所需時(shí)間和結(jié)果的靈活性之間做
個(gè)可以接受的權(quán)衡。盡管說(shuō)驅(qū)動(dòng)程序的靈活性看起來(lái)有那么點(diǎn)怪,我喜歡這個(gè)詞是因?yàn)? 它強(qiáng)調(diào)了設(shè)備驅(qū)動(dòng)程序提供的是機(jī)制,而不是策略。
機(jī)制和策略之間的差別是Unix設(shè)計(jì)背后最好的點(diǎn)子之一。實(shí)際編程中遇到的大多數(shù)問(wèn)題
都可以被劃分成兩個(gè)部分:“需要作什么”(機(jī)制)和“這個(gè)程序怎么用”(策略)。
如果這兩個(gè)主題是由程序不同部分來(lái)承擔(dān)的,或者是由不同的程序組合一起承擔(dān)的,那
么這個(gè)軟件包就很容易開發(fā),也很適合特殊需求。
舉個(gè)例子,Unix的圖形顯示管理在X服務(wù)器和窗口管理器之間劃了一道線,X服務(wù)器了解
硬件并給用戶程序提供唯一的接口,而窗口管理器實(shí)現(xiàn)特殊的策略并不需要知道硬件的
任何信息。人們可以在不同硬件上使用同樣的窗口管理器,并且不同用戶在同一臺(tái)工作
站上可以使用不同的設(shè)置。另一個(gè)例子是TCP/IP的網(wǎng)絡(luò)分層結(jié)構(gòu):操作系統(tǒng)提供抽象的
套接字操作,是設(shè)備無(wú)關(guān)的,不同服務(wù)器主管這個(gè)服務(wù)。另外,ftpd服務(wù)器提供文件傳
輸機(jī)制,而用戶可以使用任何客戶端程序;命令行的客戶端和圖形化界面的客戶端都存
在,并且誰(shuí)都可以為傳輸文件寫一個(gè)新的用戶界面。
只要涉及到驅(qū)動(dòng)程序,就會(huì)運(yùn)用這樣的功能劃分。軟盤驅(qū)動(dòng)程序是設(shè)備無(wú)關(guān)的——這不
僅表現(xiàn)在磁盤是一個(gè)連續(xù)讀寫的字節(jié)數(shù)組上。如何使用設(shè)備是應(yīng)用程序要做的事:tar要
連續(xù)地寫數(shù)據(jù),而mkfs則為要安裝的設(shè)備做準(zhǔn)備工作,mcopy依賴于設(shè)備上存在的特殊數(shù)
連續(xù)地寫數(shù)據(jù),而mkfs則為要安裝的設(shè)備做準(zhǔn)備工作,mcopy依賴于設(shè)備上存在的特殊數(shù)
據(jù)結(jié)構(gòu)。
在寫驅(qū)動(dòng)程序時(shí),程序員應(yīng)該特別留心這樣的基本問(wèn)題:我們要寫內(nèi)核代碼訪問(wèn)硬件,
但由于不同用戶有不同需要,我們不能強(qiáng)迫用戶采用什么樣的特定策略。設(shè)備驅(qū)動(dòng)程序
應(yīng)該僅僅處理硬件,將如何使用硬件的問(wèn)題留給應(yīng)用程序。如果在提供獲得硬件能力的
同時(shí)沒有增加限制,我們就說(shuō)驅(qū)動(dòng)程序是靈活的。不過(guò),有時(shí)必須要作一些策略決策。
可以從不同側(cè)面來(lái)看你的驅(qū)動(dòng)程序:它是位于應(yīng)用層和實(shí)際設(shè)備之間的軟件。驅(qū)動(dòng)程序
的程序員可以選擇這個(gè)設(shè)備應(yīng)該怎樣實(shí)現(xiàn):不同的驅(qū)動(dòng)程序可以提供不同的能力,甚至
相同的設(shè)備也可以提供不同能力。實(shí)際驅(qū)動(dòng)程序設(shè)計(jì)應(yīng)該是在眾多需求之間的一個(gè)平衡
。例如,不同程序可以同時(shí)使用同一個(gè)設(shè)備,而驅(qū)動(dòng)程序的開發(fā)者可以完全自由地決定
如何處理同步機(jī)制。你可以實(shí)現(xiàn)到設(shè)備上的內(nèi)存映射,而完成獨(dú)立于硬件的具體能力,
或者你可以提供給用戶函數(shù)庫(kù),幫助應(yīng)用程序的程序員在可用原語(yǔ)的基礎(chǔ)上實(shí)現(xiàn)新策略
,或者諸如此類的方法。一個(gè)很重要需要考慮的問(wèn)題就是,如何在提供給用戶盡可能多
的選項(xiàng),平衡你需要編寫所花費(fèi)的時(shí)間,以及為使錯(cuò)誤盡可能少而保持代碼簡(jiǎn)單之間的
平衡。
如果即為同步又為異步操作設(shè)計(jì)驅(qū)動(dòng)程序,如果允許同時(shí)打開多次,并且如果能夠發(fā)掘
所有硬件功能,而不用增加軟件層“去簡(jiǎn)化事情”——例如將二進(jìn)制數(shù)據(jù)轉(zhuǎn)換成文本或
者策略相關(guān)的操作——那就很容易編寫而且很好維護(hù)了。達(dá)成“策略無(wú)關(guān)”實(shí)際上是軟
件設(shè)計(jì)的共同目標(biāo)。
實(shí)際上,大多數(shù)設(shè)備驅(qū)動(dòng)程序是和用戶程序一起發(fā)布的,這些程序可以幫助完成對(duì)目標(biāo)
設(shè)備的配置和訪問(wèn)。這些程序可以是從簡(jiǎn)單的配置程序到完整的圖形應(yīng)用。通常還要提
供一個(gè)客戶端庫(kù)文件。
本書討論范圍是內(nèi)核,所以我們不考慮策略問(wèn)題,也不考慮應(yīng)用程序或支持庫(kù)。有時(shí),
我們會(huì)討論不同策略,以及如何支持這些策略,但我們不會(huì)深入到使用一定策略或設(shè)備
編程需要的細(xì)節(jié)問(wèn)題。不過(guò)你應(yīng)該可以理解,用戶程序是一個(gè)軟件包的內(nèi)核,就算策略
無(wú)關(guān)的軟件包也會(huì)和配置文件一起發(fā)布,這些文件提供了基本機(jī)制上的缺省行為。
劃分內(nèi)核
在Unix系統(tǒng)中,若干并發(fā)進(jìn)程會(huì)參加不同的任務(wù)。每個(gè)進(jìn)程都要求獲得系統(tǒng)資源,可以
是計(jì)算、內(nèi)存、網(wǎng)絡(luò)連接或別的資源。內(nèi)核是一整塊可執(zhí)行代碼,用它來(lái)負(fù)責(zé)處理所有
這樣的請(qǐng)求。盡管在不同的內(nèi)核任務(wù)之間的區(qū)別不是總能清楚地標(biāo)識(shí)出來(lái),內(nèi)核的作用
還是可以被劃分的。如圖1-1所示,劃分為如下這些部分:
進(jìn)程管理
內(nèi)核負(fù)責(zé)創(chuàng)建和終止進(jìn)程,并且處理它們和外部世界的聯(lián)系(輸入和輸出)。對(duì)整個(gè)系
統(tǒng)功能來(lái)講,不同進(jìn)程之間的通信(通過(guò)信號(hào),管道,進(jìn)程間通信原語(yǔ))是基本的,這
也是由內(nèi)核來(lái)處理的。另外,調(diào)度器,可能是整個(gè)操作系統(tǒng)中最關(guān)鍵的例程,是進(jìn)程管
理中的一部分。更廣廣義的說(shuō),內(nèi)核的進(jìn)程管理活動(dòng)實(shí)現(xiàn)了在一個(gè)CPU上多個(gè)進(jìn)程的抽象
概念。
概念。
內(nèi)存管理
計(jì)算機(jī)內(nèi)存是主要資源,而使用內(nèi)存的策略是影響整個(gè)系統(tǒng)性能的關(guān)鍵。內(nèi)核為每個(gè)進(jìn)
程在有限可利用的資源上建立了虛擬地址空間。內(nèi)核不同部分通過(guò)一組函數(shù)與內(nèi)存管理
子系統(tǒng)交互,這些包括從簡(jiǎn)單的malloc/free到更稀奇古怪的功能。
(圖1-1)
文件系統(tǒng)
Unix系統(tǒng)是建立在文件系統(tǒng)這個(gè)概念上的;Unix里幾乎所有東西都可以看作文件。內(nèi)核
在非結(jié)構(gòu)的硬件上建立了結(jié)構(gòu)化的文件系統(tǒng),這個(gè)抽象的文件被系統(tǒng)廣泛應(yīng)用。另外,L
inux支持多文件系統(tǒng)類型,即,物理介質(zhì)上對(duì)數(shù)據(jù)的不同組織方法。
設(shè)備控制
幾乎每種系統(tǒng)操作最后都要映射到物理設(shè)備上。除了處理器,內(nèi)存和少數(shù)其他實(shí)體外,
幾乎所有設(shè)備的控制操作都由設(shè)備相關(guān)的代碼來(lái)實(shí)現(xiàn)。這些代碼就是設(shè)備驅(qū)動(dòng)程序。內(nèi)
核必須為每個(gè)外部設(shè)備嵌入設(shè)備驅(qū)動(dòng)程序,從硬盤驅(qū)動(dòng)器到鍵盤和磁帶。內(nèi)核的這方面
功能就是本書的著眼點(diǎn)。
網(wǎng)絡(luò)
網(wǎng)絡(luò)必須由操作系統(tǒng)來(lái)管理,由于大多數(shù)網(wǎng)絡(luò)操作不是針對(duì)于進(jìn)程的:接收數(shù)據(jù)包是異
步事件。數(shù)據(jù)包必須在進(jìn)程處理它們以前就被收集,確認(rèn)和分發(fā)。系統(tǒng)通過(guò)程序和網(wǎng)絡(luò)
接口發(fā)送數(shù)據(jù)包,并且應(yīng)該可以正確地讓程序睡眠,并喚醒等待網(wǎng)絡(luò)數(shù)據(jù)的進(jìn)程。另外
,所有路由和地址解析問(wèn)題是在內(nèi)核里實(shí)現(xiàn)的。
在本書結(jié)尾部分的第16章“內(nèi)核源碼的物理布局”里,您可以看到Linux內(nèi)核的路標(biāo),但
現(xiàn)在這里的話應(yīng)該足夠了。
Linux的一個(gè)很好的特征就是,它可以在運(yùn)行的時(shí)候擴(kuò)展內(nèi)核代碼,也就是說(shuō)在系統(tǒng)運(yùn)行
的時(shí)候你可以增加系統(tǒng)的功能。
每個(gè)可以增加到內(nèi)核中的代碼稱為一個(gè)模塊。Linux內(nèi)核支持相當(dāng)多的模塊的類型(或“
類”),但不僅僅只局限于設(shè)備驅(qū)動(dòng)程序。每個(gè)模塊由目標(biāo)代碼組成(沒有連接成完整
的可執(zhí)行文件),通過(guò)insmod程序它們可以動(dòng)態(tài)連接到運(yùn)行著的內(nèi)核中,而通過(guò)rmmod程
序就可以去除這些模塊。
在圖1-1中,你可以標(biāo)別出處理不同任務(wù)的不同模塊類別——根據(jù)模塊提供的功能,每個(gè)
模塊屬于一個(gè)特定的類。
設(shè)備類和模塊
設(shè)備類和模塊
在3類設(shè)備中,Unix看待設(shè)備的方式有所區(qū)別,每種方式是為了不同的任務(wù)。Linux可以
以模塊的形式加載每種設(shè)備類型,因此允許用戶在最新版本的內(nèi)核上實(shí)驗(yàn)新硬件,跟隨
內(nèi)核的開發(fā)過(guò)程。
一考慮到模塊,每個(gè)模塊通常只實(shí)現(xiàn)一個(gè)驅(qū)動(dòng)程序,因此是可以分類的。例如,字符設(shè)
備模塊,或塊設(shè)備模塊。將模塊分成不同的類型或類并不是固定不變的;程序員可以選
擇在單獨(dú)一整塊代碼中創(chuàng)建一個(gè)模塊實(shí)現(xiàn)不同的驅(qū)動(dòng)程序。不過(guò)好的程序員會(huì)為他們實(shí)
現(xiàn)的每一個(gè)新功能創(chuàng)建不同模塊。
現(xiàn)在回到驅(qū)動(dòng)程序,有如下三種類型:
字符設(shè)備
可以象文件一樣訪問(wèn)字符設(shè)備,字符設(shè)備驅(qū)動(dòng)程序負(fù)責(zé)實(shí)現(xiàn)這些行為。這樣的驅(qū)動(dòng)程序
通常會(huì)實(shí)現(xiàn)open,close,read和write系統(tǒng)調(diào)用。系統(tǒng)控制臺(tái)和并口就是字符設(shè)備的例
子,它們可以很好地用流概念描述。通過(guò)文件系統(tǒng)節(jié)點(diǎn)可以訪問(wèn)字符設(shè)備,例如/dev/tt
y1和/dev/lp1。在字符設(shè)備和普通文件系統(tǒng)間的唯一區(qū)別是:普通文件允許在其上來(lái)回
讀寫,而大多數(shù)字符設(shè)備僅僅是數(shù)據(jù)通道,只能順序讀寫。當(dāng)然,也存在這樣的字符設(shè)
備,看起來(lái)象個(gè)數(shù)據(jù)區(qū),可以來(lái)回讀取其中的數(shù)據(jù)。
塊設(shè)備
塊設(shè)備是文件系統(tǒng)的宿主,如磁盤。在大多數(shù)Unix系統(tǒng)中,只能將塊設(shè)備看作多個(gè)塊進(jìn)
行訪問(wèn)為,一個(gè)塊設(shè)備通常是1K字節(jié)數(shù)據(jù)。Linux允許你象字符設(shè)備那樣讀取塊設(shè)備——
允許一次傳輸任意數(shù)目的字節(jié)。結(jié)果是,塊設(shè)備和字符設(shè)備只在內(nèi)核內(nèi)部的管理上有所
區(qū)別,因此也就是在內(nèi)核/驅(qū)動(dòng)程序間的軟件接口上有所區(qū)別。就象字符設(shè)備一樣,每個(gè)
塊設(shè)備也通過(guò)文件系統(tǒng)節(jié)點(diǎn)來(lái)讀寫數(shù)據(jù),它們之間的不同對(duì)用戶來(lái)說(shuō)是透明的。塊設(shè)備
驅(qū)動(dòng)程序和內(nèi)核的接口和字符設(shè)備驅(qū)動(dòng)程序的接口是一樣的,它也通過(guò)一個(gè)傳統(tǒng)的面向
塊的接口與內(nèi)核通信,但這個(gè)接口對(duì)用戶來(lái)說(shuō)時(shí)不可見的。
網(wǎng)絡(luò)接口
任何網(wǎng)絡(luò)事務(wù)處理都是通過(guò)接口實(shí)現(xiàn)的,即,可以和其他宿主交換數(shù)據(jù)的設(shè)備。通常,
接口是一個(gè)硬件設(shè)備,但也可以象loopback(回路)接口一樣是軟件工具。網(wǎng)絡(luò)接口是
由內(nèi)核網(wǎng)絡(luò)子系統(tǒng)驅(qū)動(dòng)的,它負(fù)責(zé)發(fā)送和接收數(shù)據(jù)包,而且無(wú)需了解每次事務(wù)是如何映
射到實(shí)際被發(fā)送的數(shù)據(jù)包。盡管“telnet”和“ftp”連接都是面向流的,它們使用同樣
的設(shè)備進(jìn)行傳輸;但設(shè)備并沒有看到任何流,僅看到數(shù)據(jù)報(bào)。
由于不是面向流的設(shè)備,所以網(wǎng)絡(luò)接口不能象/dev/tty1那樣簡(jiǎn)單地映射到文件系統(tǒng)的節(jié)
點(diǎn)上。Unix調(diào)用這些接口的方式是給它們分配一個(gè)獨(dú)立的名字(如eth0)。這樣的名字
在文件系統(tǒng)中并沒有對(duì)應(yīng)項(xiàng)。內(nèi)核和網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序之間的通信與字符設(shè)備驅(qū)動(dòng)程序
和塊設(shè)備驅(qū)動(dòng)程序與內(nèi)核間的通信是完全不一樣的。內(nèi)核不再調(diào)用read,write,它調(diào)用
與數(shù)據(jù)包傳送相關(guān)的函數(shù)。
事實(shí)上,Linux中還有一類“設(shè)備驅(qū)動(dòng)程序模塊”:SCSI*設(shè)備驅(qū)動(dòng)程序。盡管每個(gè)連接
到SCSI總線上的外設(shè)在/dev目錄中不是字符設(shè)備就是塊設(shè)備,但軟件的內(nèi)部組織并不完
全同。
正如網(wǎng)絡(luò)接口給網(wǎng)絡(luò)子系統(tǒng)提供硬件相關(guān)的功能一樣,SCSI控制器提供給SCSI子系統(tǒng)如
何訪問(wèn)實(shí)際接口電纜。SCSI是計(jì)算機(jī)和外設(shè)之間的通信協(xié)議,每種SCSI設(shè)備都響應(yīng)相同
的協(xié)議,與計(jì)算機(jī)插的是哪種控制板沒有關(guān)系。因此,Linux內(nèi)核嵌入一個(gè)所謂SCSI“實(shí)
現(xiàn)”(即,文件操作到SCSI通信協(xié)議的映射)。驅(qū)動(dòng)程序編寫人員必須在SCSI抽象層和
物理電纜之間實(shí)現(xiàn)這種映射。這種映射依賴于SCSI控制器,卻與SCSI電纜上連接的設(shè)備
無(wú)關(guān)。
除了設(shè)備驅(qū)動(dòng)程序,還有一些別的模塊化加載到核心中的驅(qū)動(dòng)程序,可以是軟件,也可
以時(shí)硬件。并非實(shí)現(xiàn)驅(qū)動(dòng)程序的模塊中最重要的一類是文件系統(tǒng)。文件系統(tǒng)類型是與為
了表示目錄和文件等實(shí)體的信息的組織方式相關(guān)的。因此這種實(shí)體不是“設(shè)備驅(qū)動(dòng)程序
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -