共計 3753 個字符,預計需要花費 10 分鐘才能閱讀完成。
這篇文章主要介紹“Linux 操作文件的底層系統如何調用”,在日常操作中,相信很多人在 Linux 操作文件的底層系統如何調用問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Linux 操作文件的底層系統如何調用”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!
linux 操作系統奉行一切皆文件的理念,所有文件設備幾乎都可以用一套系統調用即 open()/close()/write()/read() 等來操作。系統調用和 C 庫調用操作文件類似。Linux 自帶的 man 手冊是最權威的。通過查看 man 手冊來查看系統調用用法。
代號 mdash; mdash; 代表的含義
1 mdash; mdash; 用戶在 shell 環境下可操作 / 可執行的命令
2 mdash; mdash; 系統內核可調用的函數與工具
3 mdash; mdash; 一些常用的函數與函數庫,大部分 C 的函數庫
4 mdash; mdash; 設備文件的說明,通常是在 /dev 下的設備
5 mdash; mdash; 配置文件或某些文件的格式
6 mdash; mdash; 游戲
7 mdash; mdash; 管理與協議等,例如 Linux 文件系統、網絡協議等
8 mdash; mdash; 系統管理員可用的命令
9 mdash; mdash; 與 Kernel 有關的文件
注意,系統的頭文件在 Linux 中一般存放在 /usr/include 目錄下;下面包含的一些頭文件有的帶了 sys,其實是 include 底下的子目錄中的頭文件
open()mdash; mdash; 打開或者創建一個文件
返回值類型:int mdash; mdash; 文件描述符 fd,每打開一個文件,就會得到一個文件描述符,這個文件描述符是整形的,我們通過文件描述符進行讀寫操作。
失敗:-1
成功:= 0,即文件描述符;
mode_t 是一個類型別名,實際上就是一個有符號的整數,對 open 函數而言,僅僅當創建新文件時才使用第三個參數
flag:打開標志
注意:這些其實都是定義的一些宏,當需要使用到多個參數時,使用按位或“|”構成多個 flag 參數
也可跟隨下面的方式一起使用:
其他不一一介紹,需要使用時自查。
write()
返回值:
若成功為已經寫入的字節數;
若出錯為 -1;
注意:計劃寫入的字節數和函數的返回值不相等時,表示寫入出現了錯誤,可以用來檢驗寫入是否成功;
參數:
fd:寫入文件的文件描述符;
buf:存放待寫數據的緩存;
count:要求寫入一次數據的字節數;
注意:
對于普通文件,寫操作從文件的當前位移量處開始,若如果在打開該文件時,指定了 O_APPEND 選擇項,則在每次寫操作之前,將文件位移量設置在文件的當前結尾處。在一次成功寫之后,該文件位移量增加實際寫的字節數。
read()
返回值:讀到的字節數
若已到文件尾為 0;若出錯為 -1;
參數
fd:讀取文件的文件描述符;
buf:存放讀取數據的緩存;
count:要求讀取一次數據的字節數;注意返回值是實際讀到的字節數,二者并不相同;
注意:讀操作從文件的當前位移量開始,在成功返回之前,該位移量增加實際讀得的字節數(這個位移量是可以自己設置的);
close()
注意:當一個進程終止時,它所打開的文件都由內核自動關閉。
注:這些不帶緩存的函數都是內核提供的系統調用;這正是和我們在 C 語言中學到的那些 IO 操作不同的地方,他們不是標準 C 的組成部分,但是 POSIX 的組成部分。
標準 C 對文件操作時都是通過對 FILE 的結構體指針進行操作的,而這里使用的是文件描述符。
文件描述符的范圍是 0 mdash; mdash;OPEN MAX,早期的 Unix 采用的上限為 19(即允許每個進程打開 20 個文件),現在很多系統將即增加到 63,Linux 為 1024,具體多少可以在 unistd.h 的頭文件中查找。
文件描述符與文件指針
FILE *fdopen(int fd,const char *mode),將文件描述符轉為文件指針;
int fileno(FILE *stream),將文件指針轉換為文件描述符;
lseek 函數
功能:定位一個已打開的文件
off_t lseek(int fd,off_t offset,int whence);
fd:已經打開的文件描述符;
offset:位移量;
whence:定位的位置,即基準點
SEEK_SET:將該文件的位移量設置為距文件開始處 offset 個字節;
SEEK_CUR:將該文件的位移量設置為其當前值加 offset,offset 可正可負;
SEEK_END:將該文件的位移量設置為文件長度加 offset,offset 可正可負(此時若為正值,就涉及到空洞文件了,請看下面的講解);
返回值:** 若成功則返回新的文件位移量(絕對位移量)** 若出錯為 -1;定位到文件尾部時,可以返回文件的大小;
lseek 函數也可以用來確定所涉及的文件是否可以設置位移量,如果文件描述符所引用的是一個管道或者 FIFO,則 lseek 返回 -1,并將 errno 設置為 EPLPE;
空洞文件示例:
#include stdio.h
#include fcntl.h
#include string.h
#include stdlib.h
#include unistd.h
#include errno.h
// 生成空洞文件
char *buffer = 0123456789
int main(int argc,char *argv[])
if(argc 2)
fprintf(stderr, -usage:%s [file]\n ,argv[0]);
exit(1);
int fd = open(argv[1],O_WRONLY | O_CREATE | O_TRUNC,0777);
if(fd 0)
perror( open error
exit(1);
size_t size = strlen(buffer) * sizeof(char);
// 將字符串寫入到空洞文件中
if(write(fd,buffer,size) != size)
perror( write error
exit(1);
// 定位到文件尾部的 10 個字節處
if(lseek(fd,10L;SEERK_END) 0)
perror( lseek error
exit(1);
// 從文件尾部的 10 個字節處再寫入字符串
if(write(fd,buffer,size) != size)
perror( write error
exit(1);
close(fd);return 0;
}
我們可以看到用 more 命令查看文件內容時,發現顯示的內容只有一次寫入的結果,用 od
- c 命令查看文件的 ASSCI 碼,我們會發現在兩次內容之間,有 10 個 \0,這就是空洞,用 vim 打開該文件內容也可以看到,有 10 個 ^@符。
注:每個文件都有一個與其相關聯的“當前文件偏移量”,它是一個非負整數,用以度量從文件開始處計算的字節數。通常讀寫操作都以文件當前偏移量處開始,并使得偏移量增加所讀或所寫的字節數。按系統默認,當打開一個文件時,除非指定 O_APPEND 選擇項,否則該文件位移量被設置為 0;
示例:
運行結果如下:
fd = 3 的原因是:
系統內部 PCB 存在一個文件表,以記錄打開的文件,文件描述符其實就是文件表的下標
0 mdash; mdash;FILE* stdin,標準輸入
1 mdash; mdash;FILE* stdout,標準輸出
3 mdash; mdash;FILE* stderr,標準錯誤輸出
本程序已經默認打開了三個文件,fd 排到第四個,所以編號為 3
接下來進行文件讀取
運行結果如下:
應用:利用讀寫對文件進行復制
首先聲明:我們不區分文本文件還是二進制文件
完成對一個圖片的復制,我們可以使用以下的方案:
先打開原來的二進制文件
打開一個新的文件
從原來的二進制文件中讀取一部分寫入新文件
反復讀寫
直到讀完,寫完就停止【read() == 0 作為循環停止的條件,讀不到就是讀完了】
完成復制
復制完成
打開文件后,fork 的子進程能否共享和父進程共享訪問同一個文件?
我們每次打開文件以后,會在內核中產生 struct file 這樣一個結構體,以表示打開的文件,記錄著以下信息:
文件偏移量(起始從 0 開始,文件指針隨著寫入數據進行偏移)
引用計數(幾個進程正在使用這個打開的文件)
inode 節點(存放進程的屬性信息:誰創建了,名字是什么,在磁盤哪里存儲。通過這個 inode 節點,我們才能找到對應的這個具體的文件)
打開方式:比如只讀方式,只寫方式打開
測試 1:先打開文件再 fork
close(fd)寫在最外側,父子進程都會關閉,每關閉一次,引用計數減 1,直到為 0。
運行結果如下:
原因如下:
測試 2:先 fork 再打開文件
修改代碼后,運行結果發生如下變化:
因為父子進程分離后,打開了各自的文件,產生了各自的 struct file,不再共享文件偏移量。
在實際的應用場景中,我們更多地使用父進程打開的文件,子進程去訪問這種形式。
到此,關于“Linux 操作文件的底層系統如何調用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!
向 AI 問一下細節
丸趣 TV 網 – 提供最優質的資源集合!