linux系統呼叫和庫函式呼叫

2021-09-08 00:11:54 字數 2594 閱讀 2150

linux下對檔案操作有兩種方式:系統呼叫(system call)和庫函式呼叫(library functions)

可以參考《linux程式設計》(英文原版為《beginning linux programming》,作者是neil matthew和richard stones)第三章: working with files。

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庫的,因此也就不可能用於核心空間的驅動程式中對裝置的操作

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

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

#include 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!」 的資訊。

Linux系統呼叫和庫函式呼叫

linux下對檔案操作有兩種方式 系統呼叫 system call 和庫函式呼叫 library functions 可以參考 linux程式設計 英文原版為 beginning linux programming 作者是neil matthew和richard stones 第三章 working...

Linux系統呼叫和庫函式呼叫

linux下對檔案操作有兩種方式 系統呼叫 system call 和庫函式呼叫 library functions 可以參考 linux程式設計 英文原版為 beginning linux programming 作者是neil matthew和richard stones 第三章 working...

linux系統呼叫和庫函式呼叫的區別

linux下對檔案操作有兩種方式 系統呼叫 system call 和庫函式呼叫 library functions 可以參考 linux程式設計 英文原版為 beginning linux programming 作者是neil matthew和richard stones 第三章 working...