第5章 系統呼叫

2021-07-05 02:43:51 字數 3541 閱讀 9994

乙個穩定執行的linux作業系統需要核心和使用者應用程式之間的完美配合,核心提供各種各樣的服務,然後使用者應用程式通過某種途徑使用這些服務,

進而契合使用者的不同需求。

使用者應用程式訪問並使用核心所提供的各種服務的途徑即是系統呼叫。在核心和使用者應用程式相交界的地方,核心提供了一組系統呼叫介面,通過

這組介面,應用程式可以訪問系統硬體和各種作業系統資源。

核心提供的這組系統呼叫通常也被稱之為系統呼叫介面層。系統呼叫介面層作為核心和使用者應用程式之間的中間層,扮演了乙個橋梁,或者說中間

人的角色。系統呼叫把應用程式的請求傳達給核心,待核心處理完請求後再將處理結果返回給應用程式。

(1)系統呼叫和posix

系統呼叫雖然是核心和使用者應用程式之間的溝通橋梁,是使用者應用程式訪問核心的入口點,但通常情況下,應用程式是通過作業系統提供的應用程式設計

介面(api)而不是直接通過系統呼叫來程式設計。

作業系統api的主要作用是把作業系統的功能完全展示出來,提供給應用程式,基於該作業系統,與檔案、記憶體、時鐘、網路、圖形、各種外設等互操作

的能力。此外,作業系統api通常還提供許多任務具類的功能,比如操縱字串、各種資料型別、時間日期等。

posix標準定義了"posix相容"的作業系統所必須提供的服務。linux相容於posix標準,提供了根據posix而定義的api函式。這些api函式和系統呼叫之間

有著直接的關係,乙個api函式可以用乙個系統呼叫實現,也可以通過呼叫多個系統呼叫來實現,還可以完全不使用任何系統呼叫。

(2)系統呼叫和c庫

作業系統api通常都以c庫的方式提供,linux也是如此。c庫提供了posix的絕大部分api,同時,核心提供的每個系統呼叫在c庫中都具有相應的封裝函式。

系統呼叫與其c庫封裝函式的名稱常常相同。

c庫中的系統呼叫封裝函式在最終用到相應系統呼叫之前,往往不做多少額外的工作。不過,某些情況下會有些例外,比如對於兩個相關的系統呼叫

truncate和truncate64,c庫中的封裝函式truncate函式即需要決定它們中的哪個應該最終被呼叫。

(3)系統呼叫與系統命令

系統命令位於c庫的更上層,是利用c庫實現的可執行程式,比如最為常用的ls、cd等命令。

strace工具可以跟蹤命令的執行,使用希望跟蹤的命令為引數,並顯示出該命令執行過程中所使用到的所有系統呼叫。

(4)系統呼叫和核心函式

核心函式與c庫函式的區別僅僅是核心函式在核心實現,因此必須遵守核心程式設計的規則。

系統呼叫最終必須具有明確的操作。使用者應用程式通過系統呼叫進入核心後,會執行各個系統呼叫對應的核心函式,即系統呼叫服務歷程。

系統呼叫服務歷程之外,核心中存在著大量的核心函式。有些侷限於某個核心檔案自己使用,有些則是export出來供核心其他部分共同使用。對於

export出來的核心函式,可以使用ksyms命令或通過/proc/ksyms檔案檢視。

系統呼叫表sys_call_table儲存了所有系統呼叫對應的服務例程的函式位址,在arch/i386/kernel/syscall_table.s檔案中被定義。

有兩個特別之處,首先,所有系統呼叫服務例程的命名遵守一定的規則,即在系統呼叫名稱之前增加"sys_"字首,比如open系統呼叫對應sys_open 函式。

其次,核心提供的系統呼叫數目非常有限。

既然系統呼叫表集中存放了所有系統呼叫服務例程的位址,那麼系統呼叫在核心中的執行就可以轉化為從該錶獲取對應的服務例程並執行的過程。

這個過程中乙個很重要的環節就是系統呼叫號。每個系統呼叫都擁有乙個獨一無二的系統呼叫號,使用者應用通過它,而不是系統呼叫的名稱,來

指明要執行哪個系統呼叫。系統呼叫號的定義在include/asm-i386/unistd.h檔案

將其與sys_call_table的定義相比較可以發現,每個系統呼叫號都依次對應了sys_call_table的定義相比較可以發現,每個系統呼叫號都依次對應了

sys_call_table中的某一項。核心正是將系統呼叫號作為下標去獲取sys_call_table中的服務例程函式位址。

系統呼叫號與系統呼叫為相依相生的關係,一旦分配就不能再有任何變更,即使該系統呼叫被刪除,它所擁有的系統呼叫號也不能被**利用。

系統呼叫最終由系統呼叫服務例程完成明確的操作。所有的系統呼叫服務例程集中宣告在include/linux/syscalls.h檔案,但分散定義在很多不同的檔案。

除了都具有"sys_"字首之外,所有的系統呼叫服務例程命名與定義還必須遵守其他的一些規則。首先,函式定義中必須新增asmlinkage標記,通知

編譯器僅從堆疊中獲取該函式的函式。

其次,必須返回乙個long型別的返回值表示成功或錯誤,通常返回0表示成功,返回負值表示錯誤。當然,getpid系統呼叫非常簡單,不可能會失敗,

通過命名"man 2 getpid"可以檢視它的手冊,裡面也明確指出了這一點。

每個系統呼叫的系統呼叫號、命名以及操作目的都是固定的,但核心如何去實現並沒有明確規定,不同版本、不同架構的核心實現都有可能會有所變化。

使用者應用可以通過兩種方式使用系統呼叫。第一種方式是通過c庫函式,包括系統呼叫在c庫中的封裝函式和其他普通函式。

第二種方式是使用_syscall巨集。

系統呼叫的執行過程主要包括如圖5.3與圖5.4所示的兩個階段:使用者空間到核心空間的轉換階段,以及系統呼叫處理程式system_call函式到系統呼叫服務例程

的階段。

(1)使用者空間到核心空間

如圖5.3所示,系統呼叫的執行需要乙個使用者空間到核心空間的狀態轉換,不同的平台具有不同的指令可以完成這種轉換,這種指令也被稱作作業系統陷入指令。

(2)system_call函式到系統呼叫服務例程

(1)編寫系統呼叫服務例程

(2)新增系統呼叫號

(3)修改系統呼叫表

(4)重新編譯核心並測試

雖說新增乙個新的系統呼叫非常簡單,但這並不意味著使用者有必要這麼做。新增系統呼叫需要修改核心源**、重新編譯核心,如果更進一步希望自己新增的系統

呼叫能夠得到廣泛的應用,就需要得到官方的認可並分配乙個固定的系統呼叫號,還需要將該系統呼叫在每個需要支援的體系結構上實現。因此我們最好使用其

他替代方法和核心交換資訊,如下所示:

使用裝置驅動程式。建立乙個裝置節點,通過read和write函式進行讀寫訪問,使用ioctl函式進行設定操作和獲取特定資訊。這種方法最大的好處在於可以模組式

載入解除安裝,避免了編譯核心等過程,而且呼叫介面固定,容易操作。

使用proc虛擬檔案系統。利用proc介面獲取系統執行資訊和修訂系統狀態是一種很常見的手段,比如讀取/proc/cpuinfo可以獲得當前系統的cpu資訊,通過裝置

驅動提供的proc介面還可以設定硬體暫存器。

sysfs檔案系統。sysfs檔案系統在2.6核心被引入,是乙個類似於proc檔案系統的特殊檔案系統,用於對系統的裝置進行管理,它把實際連線到系統上的裝置和

匯流排組織成層次結構,並向使用者提供詳細的核心資料結構資訊,使用者可以利用這些資訊以實現和核心的互動。

Linxu核心設計與實現 第5章 系統呼叫

使用者程序與核心互動的介面,使應用程式受限的訪問硬體裝置,提供了建立新程序並與已有程序通訊的機制,也提供了申請作業系統其它資源的能力。應用程式發出請求,核心來滿足這些請求,或者返回乙個錯誤。1 系統呼叫在使用者空間和硬體裝置之間新增了乙個中間層 為使用者空間提供抽象的介面 保證了系統的穩定與安全 2...

第5章 系統設計 2

5.2詳細設計 詳細設計的定義 詳細設計是對軟體的各層模組和程式單元以及它們之間的相互關係的詳細描述,它是程式編碼的重要依據。詳細設計依賴於概要設計,它是對概要設計的落實和細化,詳細設計應細化到第三方根據詳細設計就可以程式設計,而可以對系統的功能需求一無所知。詳細設計的內容 詳細設計應包括以下內容 ...

第 5 章 作業系統

執行狀態 執行的所有所資源都已經配備足夠了,並且給他cpu資源 就緒狀態 其他的所有資源都配足夠了,只缺cpu資源 萬事俱備只欠東風 等待狀態 除了沒有cpu資源,還缺其他資源 不是必須缺少,但是肯定缺cpu資源 執行時缺少某個資源,進入等待狀態,等到資源配備足夠以後,不能直接 進入執行狀態,要重新...