1. 程式人生 > >系統呼叫與庫函式的區別和聯絡(API)

系統呼叫與庫函式的區別和聯絡(API)

在寫程式的過程中,像MFC,VC++這些程式設計,都會涉及到函式的呼叫,有庫函式也有系統函式,下面看一看它們的區別!!

系統呼叫(system call)和庫函式呼叫(Library function call)的區別?

理解庫函式的區別和系統呼叫,首先是kernel mode和user mode這兩個模式是這兩種函式工作時的空間不同。

一、系統呼叫:

系統呼叫實際上是指底層的一個呼叫,就是核心提供的、功能十分強大的一系列的函式。這些系統呼叫是在核心中實現的。是作業系統為使用者態執行的程序和硬體裝置(如CPU、磁碟、印表機等)進行互動提供的一組介面,即就是設定在應用程式和硬體裝置之間的一個介面層。可以說是作業系統留給使用者程式的一個介面。

例如linux核心是單核心,結構緊湊,執行速度快,各個模組之間是直接呼叫的關係。放眼整個linux系統,從上到下依次是:使用者程序->系統呼叫介面->linux核心子系統->硬體。linux核心包括了系統呼叫介面和核心子系統兩部分。或者從下到上:物理硬體->OS核心->OS服務->應用程式。這裡的OS起到了“承上啟下”的關鍵作用,向下管理物理硬體,向上為作業系統服務和應用程式提供介面,這裡的介面就是系統呼叫了。作業系統提供的少部分系統呼叫都是由C和彙編混合編寫實現的,其介面用C來定義,具體實現則是彙編,這樣的好處是執行效率高,而且極大的方便了上層的呼叫。

在linux

程式設計就是底層呼叫的意思,面向的是硬體。例如open,read,read等都是用於底層檔案的訪問(low-level file access),例如在驅動程式中對檔案的直接訪問;系統呼叫是作業系統相關的,因此一般沒有跨作業系統的可移植性;系統呼叫發生在核心空間,因此如果使用者在使用者空間的一般應用程式中使用系統呼叫來進行檔案的操作,會有使用者空間到核心空間的切換開銷。事實上,即使在使用者空間是用庫函式來對檔案進行操作,必然會引起系統的呼叫,因為檔案總是儲存在介質上的,不管是讀還是寫,都是對硬體儲存器的操做,必然引起系統呼叫。例如C庫函式fwrite和fread就是通過read和write系統函式來實現的。這樣的話,使用庫函式也有系統呼叫的開銷,為什麼不直接使用系統呼叫呢:這是因為讀寫檔案通常是大量的資料(這種大量是相對於底層驅動的系統呼叫所實現的資料操作單位而言),這時,使用庫函式就可以大大減少系統呼叫的次數(系統呼叫是一種中斷服務機制,需要提出申請佔用CPU或某些資源來對硬體訪問與操做,如I/O操作,檔案的讀取更新等)。這一結果又緣於緩衝區技術。在使用者空間和核心空間,對檔案操作都使用了緩衝區,例如用fwrite寫檔案,都是先將內容寫到使用者空間緩衝區,當用戶空間緩衝區滿或者寫操作結束時,才將使用者緩衝區的內容寫到核心緩衝區,同樣的道理,當核心緩衝區滿或寫結束時才將核心緩衝區內容寫到檔案對應的硬體媒介。

二、  庫函式:

顧名思義是把函式放到庫裡,是把一些常用到的函式編完放到一個檔案裡,供別人用。別人用的時候把所在的檔名用#include<>加到裡面就可以了,一般放到lib檔案裡。庫函式一般分為兩類:一種是C語言標準規定的庫函式,一類是編譯器特定的庫函式。libc就是一個C標準庫,裡面放著一些基本的函式,這些函式都被標準化了。

庫函式呼叫通常用於應用程式中對一般檔案的訪問,庫函式呼叫是系統無關的,因此移植性好。

庫函式主要由兩方面提供:一是作業系統提供的;另一類是由第三方提供的。

系統提供的這些函式把系統呼叫進行封裝或者組合,可以實現更多的功能,這樣的庫函式能夠實現一些對於核心來說比較複雜的操作。比如read函式根據引數,直接就能讀檔案,而背後隱藏的檔案比如在那個磁軌,那個扇區,載入到那個記憶體,是程式設計師不必關心的問題。這些操作裡面也包含了系統呼叫。

對於第三方庫,其實和系統庫一樣,只是他直接利用系統呼叫的可能性要小一些,而是系統提供的API介面來是實現(API介面是開放的)。比如printf和getchar這樣,他們都是一個“外殼”,真正實現的不是它們本身,而是呼叫了別的函式。

如printf的實現最終還是呼叫了putc()和user.h中的write()這樣的系統呼叫,而另一些則不會使用系統呼叫,比如strlen,strcat,memcpy等;庫函式大部分是對系統函式的封裝(不絕對),這個世界上很少有絕對的事兒,例如世間一切的長度和質量等數字問題都不是絕對準確的,只是一個-----約等於。

三、系統呼叫和庫函式之間的聯絡與區別:

事實上,系統呼叫所提供給使用者的是直接而純碎的高階服務,如果想要更加人性化,具有更符合特定情況的功能,那麼就要我們使用者自己定義,因此衍生了庫函式,它把部分系統呼叫包裝起來。比如當我們要用C語言列印一句話的時候,如果沒有用到庫函式printf,那麼我們就需要自己實現就需要呼叫putc()和write()等這樣一些系統函式。顯得比較麻煩,所以系統呼叫是為了方便使用作業系統的介面,而庫函式則是為了人們程式設計的方便。

庫函式的呼叫是語言或者應用程式的一部分,而系統呼叫則是作業系統的一部分。

系統呼叫是應用程式與核心互動的介面。人們在長期的程式設計中發現使用系統函式有個重大的缺點,那就是程式的移植性。例如linux提供的系統呼叫的函式和windows就不一樣。但是大部分的系統呼叫函式的速度庫函式呼叫的速度要快。

庫函式呼叫則是面向應用開發的,相當於應用程式的api,採用這樣的方式有很多原因:

(1):雙緩衝技術;

(2):移植性;

(3):底層呼叫本身存在的一些缺陷;

(4):讓api也可以有了級別和專門的工作面向;

問題一:API和系統呼叫的區別?

API(Application Programming Interface),win32API也就是MicrosoftWindows32位平臺的應用程式程式設計介面。windows規定一切的應用程式優先順序為3,為windows自己的為0(0最高,3最低)。windows不允許應用程式直接訪問硬體,但是會提供API函式讓使用者間接地訪問,這樣就會呼叫系統級API。平時出現的“...非法操作”就是因為應用程式非法訪問硬體造成的。

API分為兩種:

第一:使用者級API;替使用者寫好函式,方便呼叫,使程式設計師可以將焦點放在設計程式邏輯上面,而不必再編寫繁瑣、重複的程式,不必關注技術的細節。例如VC++,MFC,VB等都是類庫和各種控制元件,它代替了API的神祕功能。

第二:系統級API;如果應用程式想要和硬體互動,必須呼叫此類函式。程式設計師呼叫的是API(api函式),然後通過與系統呼叫共同完成函式的功能。因此,API是一個提供給應用程式的介面,一組函式,是與程式猿直接進行互動的。系統呼叫則不與程式設計師進行互動,它是根據API函式,通過一個軟體中斷機制向核心提交請求(trap指令類似於一個系統中斷,系統也會有一個特殊的中斷處理函式(interrupt handler)來處理使用者的請求),以獲得核心服務的介面。並不是所有的API函式都一一對應一個系統的呼叫,有時,一個API函式會需要幾個系統呼叫共同來完成函式的功能,甚至一些API函式不需要呼叫相應的系統呼叫,不需要核心提供的服務。

問題二:什麼是回撥函式?

回撥函式就是一個通過函式指標呼叫的函式,使用回撥函式實際上就是在呼叫某個函式(通常是API函式)時,將自己的一個函式(這個函式為回撥函式)的地址作為引數傳遞給那個函式。也就是把需要執行的程式碼地址給系統,系統在恰當的時候執行。這時你可以利用這個機會在回撥函式中處理訊息或完成一定的操作。類似於中斷處理機制,中斷在某方面使計算機變得智慧!

系統回撥函式必須是由系統呼叫,但是這個函式可以是使用者編寫的,完成相應的功能服務。