1. 程式人生 > >作業系統中最基本的概念——庫呼叫和系統呼叫

作業系統中最基本的概念——庫呼叫和系統呼叫

Unix作業系統設計上的陳述:

理解庫函式的區別和系統呼叫,首先要裡理解Unix的kernel mode和user mode。考慮下面的函式段:

int main()

{

    int fd = create("filename",0666);

    exit(0);
}

在執行main函式時,是在user mode下執行,當遇到create函式時,繼續在user mode下執行。然後系統將兩個引數"filenam"和"0666"壓入棧中或者某個暫存器,接著執行庫函式create。在庫函式create執行開始,系統仍然處在user mode下,接著系統將create系統呼叫的unique number壓入暫存器(比如說r0),然後執行指令trap(operating system trap)使系統進入kernel mode,並且處理系統呼叫。這時,系統意識到要進行系統呼叫的invoke,於是從暫存器r0中取出create系統呼叫的unique number,從系統呼叫表中查詢得知要invoke的系統呼叫是create,然後執行。執行完畢後返回庫函式create的呼叫,庫函式負責檢查系統呼叫的執行情況(檢查某些暫存器的值),然後庫函式create根據檢查的結果返回相應的值。

在這裡,trap指令類似於一個系統中斷,而系統呼叫create是一個特殊的中斷處理函式(inerrupt handler)。

APUE上的陳述:

所有作業系統都提供多種服務的入口點,由此程式向系統核請求服務。各種版本的Unix都
提供經良好定義的有限數目的入口點,經過這些入口點進入系統核,這些入口點被稱之為
系統呼叫(system call),系統呼叫是我們不能更改的一種Unix特徵。Unix版本7提供了約
50個系統呼叫,4 3+BSD提供了約110個,而SVR4則提供了約120個。

系統呼叫介面總是在Unix程式設計師手冊的第二部分中說明。其定義也包括在C語言中。這與很
多較早期的作業系統是不同的,這些系統按傳統都在機器的組合語言中定義系統核入口點。

Unix所使用的技術是為每條系統呼叫在標準C庫中設定一個具有同樣名字的函式。使用者程序
用標準C呼叫序列來呼叫這些函式,然後,函式用系統所要求的技術呼叫相應的系統核服務
。例如函式可將一個或幾個C引數送入通用暫存器,然後執行某個產生軟中斷進入系統核的
機器指令。從應用角度考慮,我們可將系統呼叫視作為C函式。

Unix程式設計師手冊的第三部分定義了程式設計師可以使用的通用函式。雖然這些函式可能會呼叫
一個或幾個系統核的系統呼叫,但是它們並不是系統核的入口點。例如,printf函式會調
用write系統呼叫以進行輸出操作,但函式strcpy(複製一字串)和atoi(變換ASCII為整數
)並不使用任何系統呼叫。

從實施者的角度,系統呼叫和庫函式之間有重大區別,但從使用者角度其區別並不非常重要。
從本書的目的出發,系統呼叫和庫函式在本書中都以正常的C函式的形式出現。兩者都對應
用程式提供服務,但是,我們應當理解,如果希望的話,我們可以代換庫函式,但是通常
我們卻不能代換系統服務。

以儲存器分配函式malloc為例。有多種方法可以進行儲存器分配及與其相關的無用區收集
操作(最佳適應,首次適應等),並不存在對所有程式都最佳的一種技術。Unix系統呼叫中
處理儲存器分配的是sbrk(2),它不是一個通用的儲存器管理器。它增加或減少指定位元組數
的程序地址空間。如何管理該地址空間卻取決於程序。儲存器分配函式malloc(3)實現一
種特定型別的分配。如果我們不喜歡其操作方式,則我們可以定義自己的malloc函式,極
其可能,它還是要呼叫sbrk系統呼叫。事實上,有很多軟體包,它們實現自己的儲存器分
配演算法,但仍使用sbrk系統呼叫。

從中可見,兩者職責不同,相互分開,要核中的系統呼叫分配另外一塊空間給程序,而庫
函式malloc則管理這種空間。

另一個可說明系統呼叫和庫函式之間的差別的例子是,Unix提供決定當前時間和日期的界
面。某些作業系統提供一個系統呼叫以返回時間,而另一個則返回日期。任何特殊的處理
,例如正常時制和日光節約時制之間的轉換,由系統核處理或要求人的幹予。Unix則不同
,它只提供一條系統呼叫,該系統呼叫返回國際標準時公元一九七年一月一日午夜來所以
經過的秒數。對該值的任何解釋,例如將其變換成人們可讀的,使用本地時區的時間和日
期,都留給使用者程序執行。在標準C庫中,提供了若干例程以處理大多數情況。這些庫函式
處理各種細節,例如各種日光節約時演算法。

應用程式可以或者呼叫系統呼叫,或者庫函式,而很多庫函式則會呼叫系統呼叫。
另一個系統呼叫和庫函式之間的差別是:系統呼叫通常提供一種最小介面,而庫函式通常
提供比較複雜的功能。我們從sbrk系統呼叫和malloc庫函式之間的差別中看到了這一點,
在以後當比較不帶快取的I/O庫數(第3章)以及標準I/O標準(在第5章)時,我們還將看到這
種差別。

程序控制系統呼叫(fork,exec和wait)通常由使用者的應用程式直接呼叫。(請回憶程式1.5中
的基本shell)但是為了簡化某些常見的情況,UNIX系統也提供了一些庫函式;例如system
和popen。在8.12節中,我們將說明system函式的一種實現,它使用基本的程序控制系統調
用。在10.18中,我們還將強化這一例項以正確地處理訊號。

為使讀者瞭解大多數程式設計師應用的Unix系統介面,我們不得不既說明系統呼叫,只介紹某
些庫函式。例如若我們只說明sbrk系統呼叫,那麼就會忽略很多應用程式使用的malloc庫函式

在本書中,除了一定要將兩者相區分時,我們都將使用術語"函式"來涉及系統呼叫和庫函
數兩者。

簡明的回答是:函式庫呼叫是語言或應用程式的一部分,而系統呼叫是作業系統的一部分。你要確保弄懂“trap(自陷)”這個關鍵字的含義。系統呼叫是在作業系統核心發現一個“trap”或中斷後進行的。 ※函式庫呼叫 VS 系統呼叫

函式庫呼叫

系統呼叫

在所有的ANSI C編譯器版本中,C庫函式是相同的

各個作業系統的系統呼叫是不同的

它呼叫函式庫中的一段程式(或函式)

它呼叫系統核心的服務

與使用者程式相聯絡

是作業系統的一個入口點

在使用者地址空間執行

在核心地址空間執行

它的執行時間屬於使用者時間

它的執行時間屬於系統時間

屬於過程呼叫,呼叫開銷較小

需要在使用者空間和核心上下文環境間切換,開銷較大

C函式庫libc中有大約300個函式

UNIX中大約有90個系統呼叫

典型的C函式庫呼叫:system fprintf malloc

典型的系統呼叫:chdir fork write brk

庫函式呼叫通常比行內展開的程式碼慢,因為它需要付出函式呼叫的開銷。但系統呼叫比庫函式呼叫還要慢很多,因為它需要把上下文環境切換到核心模式。