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