一般地,操作系統爲了考慮實現的難度和管理的方便,它只提供一少部分的系統調用,這些系統調用一般都是由C和彙編混合編寫實現的,其接口用C來定義,而具體的實現則是彙編,這樣的好處就是執行效率高,而且,極大的方便了上層調用。
庫函數:顧名思義是把函數放到庫裏。是把一些常用到的函數編完放到一個文件裏,供別人用。別人用的時候把它所在的文件名用#include<>加到裏面就可以了。一般是放到lib文件裏的。一般是指編譯器提供的可在c源程序中調用的函數。可分爲兩類,一類是c語言標準規定的庫函數,一類是編譯器特定的庫函數。(由於版權原因,庫函數的源代碼一般是不可見的,但在頭文件中你可以看到它對外的接口)
libc中就是一個C標準庫,裏面存放一些基本函數,這些基本函數都是被標準化了的,而且這些函數通常都是用匯編直接實現的。
庫函數一般可以概括的分爲兩類,一類是隨着操作系統提供的,另一類是由第三方提供的。隨着系統提供的這些庫函數把系統調用進行封裝或者組合,可以實現更多的功能,這樣的庫函數能夠實現一些對內核來說比較複雜的操作。比如,read()函數根據參數,直接就能讀文件,而背後隱藏的比如文件在硬盤的哪個磁道,哪個扇區,加載到內存的哪個位置等等這些操作,程序員是不必關心的,這些操作裏面自然也包含了系統調用。而對於第三方的庫,它其實和系統庫一樣,只是它直接利用系統調用的可能性要小一些,而是利用系統提供的API接口來實現功能(API的接口是開放的)。部分Libc庫中的函數的功能的實現還是藉助了系統掉調用,比如printf的實現最終還是調用了write這樣的系統調用;而另一些則不會使用系統調用,比如strlen, strcat, memcpy等。
實時上,系統調用所提供給用戶的是直接而純粹的高級服務,如果想要更人性化,具有更符合特定情況的功能,那麼就要我們用戶自己來定義,因此就衍生了庫函數,它把部分系統調用包裝起來,一方面把系統調用抽象了,一方面方便了用戶級的調用。系統調用和庫函數在執行的效果上很相似(當然庫函數會更符合需求),但是系統調用是運行於內核狀態;而庫函數由用戶調用,運行於用戶態。
系統調用是爲了方便使用操作系統的接口,而庫函數則是爲了人們編程的方便。
從實施者的角度,系統調用和庫函數之間有重大區別,但從用戶角度其區別並不非常重要。 兩者都對應 用程序提供服務,但是,我們應當理解,如果希望的話,我們可以代庫函數,但是通常我們卻不能代換系統服務。
以存儲器分配函數malloc爲例。有多種方法可以進行存儲器分配及與其相關的無用區收集操作(最佳適應,首次適應等),並不存在對所有程序都最佳的一種技術。Unix系統調用中處理存儲器分配的是sbrk(2),它不是一個通用的存儲器管理器。它增加或減少指定字節數的進程地址空間。如何管理該地址空間卻取決於進程。存儲器分配函數malloc(3)實現一種特定類型的分配。如果我們不喜歡其操作方式,則我們可以定義自己的malloc函數,極 其可能,它還是要調用sbrk系統調用。事實上,有很多軟件包,它們實現自己的存儲器分配算法,但仍使用sbrk系統調用。從中可見,兩者職責不同,相互分開,要核中的系統調用分配另外一塊空間給進程,而庫函數malloc則管理這種空間。
另一個可說明系統調用和庫函數之間的差別的例子是,Unix提供決定當前時間和日期的界面。某些操作系統提供一個系統調用以返回時間,而另一個則返回日期。任何特殊的處理,例如正常時制和日光節約時制之間的轉換,由系統核處理或要求人的幹予。Unix則不同,它只提供一條系統調用,該系統調用返回國際標準時公元一九七年一月一日午夜來所以經過的秒數。對該值的任何解釋,例如將其變換成人們可讀的,使用本地時區的時間和日 期,都留給用戶進程運行。在標準C庫中,提供了若干例程以處理大多數情況。這些庫函數 處理各種細節,例如各種日光節約時算法。