Linux下對檔案操作有兩種方式:系統調用(system call)和庫函數調用(Library functions)。可以參考《Linux程式設計》(英文原版為《Beginning Linux Programming》,作者是Neil Matthew和Richard Stones)第三章: Working with files。系統調用實際上就是指最底層的一個調用,在linux程式設計裡面就是底層調用的意思。面向的是硬體。而庫函數調用則面向的是應用開發的,相當於應用程式的api,採用這樣的方式有很多種原因,第一:雙緩衝技術的實現。第二,可移植性。第三,底層調用本身的一些效能方面的缺陷。第四:讓api也可以有了層級和專門的工作面向。
1、系統調用
系統調用提供的函數如open, close, read, write, ioctl等,需包含標頭檔unistd.h。以write為例:其函數原型為 size_t write(int fd, const void *buf, size_t nbytes),其操作對象為檔案描述符或檔案控制代碼fd(file descriptor),要想寫一個檔案,必須先以可寫入權限用open系統調用開啟一個檔案,獲得所開啟檔案的fd,例如 fd=open(\"/dev/video\", O_RDWR)。fd是一個整型值,每新開啟一個檔案,所獲得的fd為當前最大fd加1。Linux系統預設分配了3個檔案描述符值:0-standard input,1-standard output,2-standard error。
系統調用通常用於底層檔案訪問(low-level file access),例如在驅動程式中對裝置檔案的直接存取。
系統調用是作業系統相關的,因此一般沒有跨作業系統的可移植性。
系統調用發生在核心空間,因此如果在使用者空間的一般應用程式中使用系統調用來進行檔案操作,會有使用者空間到核心空間切換的開銷。事實上,即使在使用者空間使用庫函數來對檔案進行操作,因為檔案總是存在於儲存介質上,因此不管是讀寫操作,都是對硬體(儲存空間)的操作,都必然會引起系統調用。也就是說,庫函數對檔案的操作實際上是通過系統調用來實現的。例如C庫函數fwrite()就是通過write()系統調用來實現的。
這樣的話,使用庫函數也有系統調用的開銷,為什麼不直接使用系統調用呢?這是因為,讀寫檔案通常是大量的資料(這種大量是相對於底層驅動的系統調用所實現的資料操作單位而言),這時,使用庫函數就可以大大減少系統調用的次數。這一結果又緣於緩衝區技術。在使用者空間和核心空間,對檔案操作都使用了緩衝區,例如用fwrite寫檔案,都是先將內容寫到使用者空間緩衝區,當使用者空間緩衝區滿或者寫操作結束時,才將使用者緩衝區的內容寫到核心緩衝區,同樣的道理,當核心緩衝區滿或寫結束時才將核心緩衝區內容寫到檔案對應的硬體媒介。
2、庫函數調用
標準C庫函數提供的檔案操作函數如fopen, fread, fwrite, fclose, fflush, fseek等,需包含標頭檔stdio.h。以fwrite為例,其函數原型為size_t fwrite(const void *buffer, size_t size, size_t item_num, FILE *pf),其操作對象為檔案指標FILE *pf,要想寫一個檔案,必須先以可寫入權限用fopen函數開啟一個檔案,獲得所開啟檔案的FILE結構指標pf,例如pf=fopen(\"~/proj/filename\", \"w\")。實際上,由於庫函數對檔案的操作最終是通過系統調用實現的,因此,每開啟一個檔案所獲得的FILE結構指標都有一個核心空間的檔案描述符fd與之對應。同樣有相應的預定義的FILE指標:stdin-standard input,stdout-standard output,stderr-standard error。
庫函數調用通常用於應用程式中對一般檔案的訪問。
庫函數調用是系統無關的,因此可移植性好。
由於庫函數調用是基於C庫的,因此也就不可能用於核心空間的驅動程式中對裝置的操作。
※函數庫調用 VS 系統調用
| 函數庫調用 |
系統調用 |
| 在所有的ANSI C編譯器版本中,C庫函數是相同的 |
各個作業系統的系統調用是不同的 |
| 它調用函數庫中的一段程式(或函數) |
它調用系統核心的服務 |
| 與使用者程式相聯絡 |
是作業系統的一個進入點 |
| 在使用者地址空間執行 |
在核心地址空間執行 |
| 它的已耗用時間屬於“使用者時間” |
它的已耗用時間屬於“系統”時間 |
| 屬於程序呼叫,調用開銷較小 |
需要在使用者空間和核心上下文環境間切換,開銷較大 |
| 在C函數庫libc中有大約300個函數 |
在UNIX中大約有90個系統調用 |
| 典型的C函數庫調用:system fprintf malloc |
典型的系統調用:chdir fork write brk; |
原文地址:http://www.spridu.cn/article/Linux_unix/2011/02/17/linux-systemcall-distinction-libraryfunction_9178.shtml