文章目錄
- 文件系統調用接口
- open
- 系統調用接口和C語言封裝
- 文件描述符fd
- 重定向
文件系統調用接口
open
NAME//打開、創建 - 打開并可能創建文件或設備open, creat - open and possibly create a file or deviceSYNOPSIS#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);int creat(const char *pathname, mode_t mode);
給定一個文件路徑,open返回一個文件描述符,一個小的非負整數,用于后續的系統調用。成功調用返回的文件描述符將是當前未為進程打開的編號最低的文件描述符。
flags
參數標志必須包括以下訪問結點之一:O_RDONLY、O_WRONLY、O_RDWR.著三種方式分別表示只讀、只讀或讀/寫文件。
- O_APPEND
文件以追加的模式打開。每次寫入之前,文件偏移量位于文件的末尾。 - O_CREAT
如果文件不存在,則創建它。將文件的所有者,設置為進程的有效用戶ID。組所屬者設置為進程的有效組ID,也可以設置為父目錄的組ID。 - mode參數,模式指定在創建新文件時要使用的權限。當在flags中指定使用O_CREAT時,必須提供此參數,如果未使用O_CREAT,則忽略mode。
有效的權限由進程的umask按照通常的方式修改。
系統調用接口和C語言封裝
- 以寫的方式打開,如果文件不存在則創建
fopen("log1.txt",w);
open("log1.txt", O_WRONLY|O_CREAT|O_TRUNC,0666)
- 以追加的方式打開,如果文件不存在則創建
fopen("log1.txt",a);
open("log1.txt",O_WRONLY|O_APPEND|O_CREAT,0666);
庫函數:類似fopen
、fclose
、fwrite
、fread
都是C標準庫中的函數,庫函數
系統調用接口:類似open
、close
、write
、read
都屬于系統提供的接口,系統調用接口
C語言庫函數中的f*
系列的函數,都是對系統調用的二次封裝,方便二次開發。
在操作系統提供了類似open這種調用接口的情況下,C語言仍然對其進行了封裝,主要原因是為了保證程序的可移植性和跨平臺性。
文件描述符fd
- Linux進程默認情況下會有3個缺省打開的文件描述符,分別是標準輸入0,標準輸出1,標準錯誤2.
- 0、1、2對應的物理設備一般是:鍵盤、顯示器、顯示器
每個打開文件,在內核當中都有file對象那個,保存了文件相關的inode元信息。
文件描述符的本質就是數組的下標。
文件描述符就是從0開始的小整數。
當我們打開文件時操作系統在內存中要創建相應的數據結構來描述目標文件。于是就有了file結構體,表示一個已經打開的文件對象。而進程執行open系統調用,所以必須讓進程和文件關聯起來。每個進程都有一個指針*files
,指向一張表file_struct,該表最重要的部分就是包含一個指針數組,每個元素都是一個指向打開文件的指針!所以,本質上,文件描述符就是該數組的小標。所以,只要拿著文件描述符,就可以找到對應的文件。
文件描述符分配規則
在files_struct數組當中,找到當前沒有被使用的最小的一個下標,做為新打開的文件描述符。
重定向
Linux下一切皆文件
對于每一種硬件,操作系統都有對應的系統調用接口
close(1);
const char* buffer = "hello open";
int fd2 = open("log2.txt",O_WRONLY|O_APPEND|O_CREAT,0666);
printf("hello open\n");
上段代碼,在執行之后,預期是在顯示器上輸出hello open
,但是實際上不是。
在實際的運行之后,本應該打印在顯示器上的數據,卻寫入到了log2.txt
文件中。
現象解釋:
- 當程序執行close(1)之后,文件描述符數組中的1號下標位置,本應指向的stdout文件(標準輸出文件)被關閉,此時文件描述符數組中下標最小的是1號下標。
- 執行到open語句的時候,需要打開當前目錄下的
log2.txt
文件,但是不存在,所以此時創建一個新的文件,這個新的文件,在files_struct數組當中,找到當前沒有被使用的最小的一個下標,做為新打開的文件描述符。所以此時log2.txt
文件的fd就是1. - 對于printf函數,此函數默認將數據寫入到stdout標準輸出流文件中,也就是文件描述符的1號下標處。但是此時1號下標已經指向了新打開的文件,所以數據寫入到了
log2.txt
文件中。