系統呼叫和庫函式

2021-04-21 14:38:51 字數 3962 閱讀 2599

《unix 環境高階程式設計》一書中如此說:

所有作業系統都提供多種服務的入口點,由此程式向系統核請求服務。各種版本的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)實現一

其可能,它還是要呼叫sbrk系統呼叫。事實上,有很多軟體包,它們實現自己的儲存器分

配演算法,但仍使用sbrk系統呼叫。圖1.1顯示了應用程式、malloc函式以及sbrk系統呼叫之

間的關係。

圖1.2〓malloc函式和sbrk系統呼叫 

從中可見,兩者職責不同,相互分開,要核中的系統呼叫分配另外一塊空間給程序,而庫

函式malloc則管理這種空間。 

另乙個可說明系統呼叫和庫函式之間的差別的例子是,unix提供決定當前時間和日期的界

面。某些作業系統提供乙個系統呼叫以返回時間,而另乙個則返回日期。任何特殊的處理

,例如正常時制和日光節約時制之間的轉換,由系統核處理或要求人的幹予。unix則不同

,它只提供一條系統呼叫,該系統呼叫返回國際標準時公元一九七年一月一日午夜來所以

經過的秒數。對該值的任何解釋,例如將其變換**們可讀的,使用本地時區的時間和日

期,都留給使用者程序執行。在標準c庫中,提供了若干例程以處理大多數情況。這些庫函式

處理各種細節,例如各種日光節約時演算法。 

應用程式可以或者呼叫系統呼叫,或者庫函式,而很多庫函式則會呼叫系統呼叫。這在圖1

.3中顯示。

圖1.3〓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庫函式

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

數兩者。

《the linux kernel module programming guide》書中如此描述:

庫函式是高層的,完全執行在使用者空間, 為程式設計師提供呼叫真正的在幕後完成實際事務的系統呼叫的更方便的介面。系統呼叫在核心態執行並且由核心自己提供。標準c庫函式printf()可以被看做是乙個通用的輸出語句,但它實際做的是將資料轉化為符合格式的字串並且呼叫系統呼叫write()輸出這些字串。

是否想看一看printf()究竟使用了哪些系統呼叫? 這很容易,編譯下面的**。

#i nclude 

int main(void)

使用命令gcc -wall -o hello hello.c編譯。用命令strace hello跟蹤該可執行檔案。是否很驚訝? 每一行都和乙個系統呼叫相對應。 strace是乙個非常有用的程式,它可以告訴你程式使用了哪些系統呼叫和這些系統呼叫的引數,返回值。 這是乙個極有價值的檢視程式在幹什麼的工具。在輸出的末尾,你應該看到這樣類似的一行write(1, "hello", 5hello)。這就是我們要找的。藏在面具printf()的真實面目。既然絕大多數人使用庫函式來對檔案i/o進行操作(像 fopen, fputs, fclose)。 你可以檢視man說明的第二部分使用命令man 2 write。man說明的第二部分專門介紹系統呼叫(像kill()read())。 man說明的第三部分則專門介紹你可能更熟悉的庫函式(像cosh()random())。

你甚至可以編寫**去覆蓋系統呼叫,正如我們不久要做的。駭客常這樣做來為系統安裝後門或木馬。 但你可以用它來完成一些更有益的事,像讓核心在每次某人刪除檔案時輸出 「 tee hee, that tickles!」 的資訊。

自己總結:

從程式完成的功能來看,函式庫提供的函式通常是不需要作業系統的服務,函式是在使用者空間內執行的,除非函式涉及到i/o操作等,一般是不會切到核心態的。系統呼叫是要求作業系統為使用者提供程序,提供某種服務,通常是涉及系統的硬體資源和一些敏感的軟體資源等。

函式庫的函式,尤其與輸入輸出相關的函式,大多必須通過linux的系統呼叫來完成。因此我們可以將函式庫的函式當成應用程式設計人員與系統呼叫程式之間的乙個中間層,通過這個中間層,我們可以用一致的介面來安全的呼叫系統呼叫。這樣程式設計師可以只要寫一次**就能夠在不同版本的linux系統間使用積壓種具體實現完全不同的系統呼叫。至於如何實現對不同的系統呼叫的相容性問題,那是函式庫開發者所關心的問題。

從程式執行效率來看,系統呼叫的執行效率大多要比函式高,尤其是處理輸入輸出的函式。當處理的資料量比較小時,函式庫的函式執行效率可能比較好,因為函式庫的作法是將要處理的資料先存入緩衝區內,等到緩衝區裝滿了,再將資料一次寫入或者讀出。這種方式處理小量資料時效率比較高,但是在進行系統呼叫時,因為使用者程序從使用者模式進入系統核心模式,中間涉及了許多額外的任務的切換工作,這些操作稱為上下文切換,此類的額外工作會影響系統的執行效率。但是當要處理的資料量比較大時,例如當輸入輸出的資料量超過檔案系統定義的盡寸時,利用系統呼叫可獲得較高的效率。

從程式的可移植性的角度來看,相對於系統呼叫,c語言的標準備函式庫(ansi c) 具備較高的可移植性,在不同的系統環境下,只要做很少的修改,通常情況是不需要修改的。

系統呼叫和庫函式

在計算機中,系統呼叫 英語 system call 又稱為系統呼叫,指執行在使用者空間的程式向作業系統核心請求需要更高許可權執行的服務。系統呼叫提供了使用者程式與作業系統之間的介面。大多數系統互動式操作需求在核心態執行。如裝置io操作或者程序間通訊。庫函式是在系統呼叫上的一層包裝,執行在使用者態 u...

系統呼叫和庫函式

系統呼叫概述 系統呼叫,我們可以理解是作業系統為使用者提供的一系列操作的介面 api 這些介面提供了對系統硬體裝置功能的操作。這麼說可能會比較抽象,舉個例子,我們最熟悉的 hello world 程式會在螢幕上列印出資訊。程式中呼叫了 printf 函式,而庫函式 printf 本質上是呼叫了系統呼...

系統呼叫和庫函式

這一部分主要是為了使用者能夠方便的和作業系統互動,由此作業系統提供了使用者介面,讓使用者或者開發人員通過這些介面方便的與系統進行互動。使用者介面分為三部分 命令介面 windows中為cmd命令列,linux中為terminal,使用者可以通過執行命令完成相應的任務 程式介面 系統程式是取得作業系統...