本篇涉及文件的創建、打開、讀和關閉。
文件為操作系統服務和設備提供了一個簡單而一致的 接口
。“接口”指的是一種約定或標準,通過提供一個一致的接口,可以為上層隱藏底層硬件和服務的復雜性,上層無需關注它們的具體實現細節。
比如操作系統中的文件系統。文件可以存儲在硬盤上,也可以存儲在光盤上、磁帶上。不同的硬件之間差別很大,文件系統也不相同。但是只需要抽象出 5 個基本的函數:open
、close
、read
、write
和 ioctl
,應用程序就可以不用理會文件用的是什么文件系統、存儲在哪里,就可以完成文件的操作。這 5 個基本函數的定義就是接口。
在 Linux 中,一切(或幾乎一切)都是文件。
操作系統的核心部分,即內核,是一組 設備驅動程序
。它們是一組對系統硬件進行控制的底層 接口
。
為了向用戶提供一個一致的接口,設備驅動程序封裝了所有與硬件相關的特性。硬件的特有功能通常可通過 ioctl
(用于 I/O 控制) 系統調用來提供。
低層次文件訪問
使用 系統調用
函數訪問文件,屬于低層次文件訪問方式。
write 函數
#include <unistd.h>
#include <stdlib.h>
#include <string.h>int main(int argc, char *argv[])
{char *test_str = "Here is some data\n";write(1, test_str, strlen(test_str));exit(0);
}
- 頭文件
unistd.h
包含了許多與 POSIX 操作系統 API 相關的定義和函數原型,例如write
函數。 - 頭文件
stdlib.h
包含exit
函數 - 頭文件
string.h
包含處理字符串的函數原型,例如strlen
。 write
函數是系統調用,原型為size_t write (int __fd, const void *__buf, size_t __n)
,在本例中,將 test_str 中的內容寫入到文件描述符 1 所代表的設備上(標準輸入)。
write 函數返回寫入的字節數,出錯返回 -1。- 調用
exit
函數來結束程序。這里的參數0表示程序正常退出。
read 函數
#include <unistd.h>
#include <stdlib.h>
#include <string.h>int main(int argc, char *argv[])
{char error_read_message[] = "Error writing to stdout\n";char buffer[8];int nread;nread = read(0, buffer, 8);if(nread == -1)write(2, error_read_message, strlen(error_read_message));write(1, buffer, nread);exit(0);
}
- 調用
read
函數從文件描述符 0(即標準輸入)讀取最多 8 個字節的數據到 buffer 中,并將讀取的字節數存儲在 nread 中。注意它返回實際讀入的字節數,這可能會小于 8 。 - 讀取最多 8 個字節數據,這表示多于 8 個字符時,只會取前 8 個字符,不會導致溢出。
- 在 shell 中運行這個程序,read 函數從標志輸入中讀取數據,shell 將標準輸入映射到鍵盤上。當按下回車鍵時,shell 將輸入的內容發送給程序。注意輸入的數據包含換行符。