1. 程式人生 > >庫函式與系統呼叫的區別

庫函式與系統呼叫的區別

Linux對檔案操作有兩種形式:系統呼叫與庫函式呼叫。

一、系統呼叫

系統呼叫是通向作業系統本身的介面,是面向底層硬體的。通過系統呼叫,可以使得使用者態執行的程序與硬體裝置(如CPU、磁碟、印表機等)進行互動,是作業系統留給應用程式的一個介面。下面適用於訪問裝置驅動程式的系統呼叫:

open: 開啟檔案或裝置
read: 從開啟的檔案或裝置中讀取資料
write: 向開啟的檔案或裝置中寫入資料
close: 關閉檔案或裝置
ioctl: 把控制資訊傳遞給裝置驅動檔案

使用者程序需要發生系統呼叫時,核心將呼叫核心相關函式來實現(如sys_read(),sys_write(),sys_fork())。使用者程式不能直接呼叫這些函式,這些函式執行在核心態,CPU 通過軟中斷切換到核心態開始執行核心系統呼叫函式。

使用者態–>系統呼叫–>核心態–>返回使用者態

實際上使用系統呼叫會影響系統的效能,在執行呼叫時的從使用者態切換到核心態,再返回使用者態會有系統開銷。為了減少開銷,因此需要減少系統呼叫的次數,並且讓每次系統調用盡可能的完成多的任務。硬體也會限制對底層系統呼叫一次所能寫的資料塊的大小。為了給裝置和檔案提供更高層的介面,Linux系統提供了一系列的標準函式庫。使用標準庫函式,可以高效的寫任意長度的資料塊,庫函式在資料滿足資料塊長度要求時安排執行底層系統呼叫。

一般地,作業系統為了考慮實現的難度和管理的方便,它只提供一少部分的系統呼叫,這些系統呼叫一般都是由C和彙編混合編寫實現的,其介面用C來定義,而具體的實現則是彙編,這樣的好處就是執行效率高,而且,極大的方便了上層呼叫。


二、庫函式

庫函式(Library function)是把函式放到庫裡,供別人使用的一種方式。.方法是把一些常用到的函式編完放到一個檔案裡,供不同的人進行呼叫。一般放在.lib檔案中。庫函式呼叫則是面向應用開發的,庫函式可分為兩類,一類是c語言標準規定的庫函式,一類是編譯器特定的庫函式。(由於版權原因,庫函式的原始碼一般是不可見的,但在標頭檔案中你可以看到它對外的介面)。

glibc 是 Linux 下使用的開源的標準 C 庫,它是 GNU 釋出的 libc 庫,即執行時庫。這些基本函式都是被標準化了的,而且這些函式通常都是用匯編直接實現的。glibc 為程式設計師提供豐富的 API(Application Programming Interface),我們經常說到的POSIX(Portable Operating System Interface of Unix)是針對API的標準,即針對API的函式名,返回值,引數型別等。POSIX相容也就指定這些介面函式相容,但是並不管API具體如何實現。

隨著系統提供的這些庫函式把系統呼叫進行封裝或者組合,可以實現更多的功能,這樣的庫函式能夠實現一些對核心來說比較複雜的操作。比如,read()函式根據引數,直接就能讀檔案,而背後隱藏的比如檔案在硬碟的哪個磁軌,哪個扇區,載入到記憶體的哪個位置等等這些操作,程式設計師是不必關心的,這些操作裡面自然也包含了系統呼叫。而對於第三方的庫,它其實和系統庫一樣,只是它直接利用系統呼叫的可能性要小一些,而是利用系統提供的API介面來實現功能(API的介面是開放的)。部分Libc庫中的函式的功能的實現還是藉助了系統掉呼叫,比如printf的實現最終還是呼叫了write這樣的系統呼叫;而另一些則不會使用系統呼叫,比如strlen, strcat, memcpy等。
這裡寫圖片描述
系統呼叫是為了方便使用作業系統的介面,而庫函式則是為了人們程式設計的方便。

庫函式呼叫與系統無關,不同的系統,呼叫庫函式,庫函式會呼叫不同的底層函式實現,因此可移植性好。由於庫函式是基於c庫的,因此不能用於核心對於底層驅動裝置的操作。
這裡寫圖片描述