
?
Linux 應用編程中最需要掌握的基礎就是文件 I/O的操作,學習過linux或者有過了解的應該都會聽過一句話:linux中一切皆文件,文件是linux系統的核心設計思想。所以掌握文件的操作是很重要的。
(資料圖片)
那文件 I/O 又是什么?文件I/O指的是對文件的輸入/輸出操作,簡單點說就是對文件進行的讀寫操作,包括打開文件、關閉文件、從文件中讀取數據和向文件中寫入數據等的操作。
本文就分享linux下的一些文件的簡單操作,涉及文件描述符、文件打開、讀文件、寫文件、文件指針lseek。
linux中打開的文件不管是現有文件還是新創建的文件,內核都會為文件分配一個編號,這個編號用于指代這個被打開的文件,在IO操作中會返回到進程中,這個編號就是文件描述符。
文件描述符對于一個進程來說是一種有限資源,并不是無限的。
一個進程中的文件描述符是從 0 開始分配的,一直到最大的文件描述的數量位置。
假如說進程中最大的文件描述符數量為1024個,而第一個被打開的文件對應的文件描述符是 0、第二個文件是 1、第三個文件是 2、第 4 個文件是 3……以此類推,所以由此可知,文件描述符數字最大值為 1023(0~1023)。
每一個被打開的文件在同一個進程中都有一個唯一的文件描述符,不會重復,如果文件被關閉后,它對應的文件描述符將會被釋放,那么這個文件描述符將可以再次分配給其它打開的文件、與對應的文件綁定起來。
對于linux系統中進程允許打開的最大的文件數是多少,可以用指令進行查看,如下:
ulimit -n
如下示例:
注意:在實際使用中,我們在程序調用函數打開文件的時,分配的文件描述符一般都是從 3 開始,0、1、2 這三個文件描述符是默認被系統占用的,它們分配給了系統標準輸入(0)、標準輸出(1)、標準錯誤(2)。
Linux 系統中要操作一個文件,需要先打開該文件,得到文件描述符,然后再對文件進行相應的操作。
open 函數用于打開文件,它除了能打開已經存在的文件,還能創建新的文件。函數原型如下:
#include#include #include int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);
使用linux時,如果想要查看某些系統調用API函數的原型和用法,可以通過man命令獲得幫助,如下:
man 2 open
函數open的幫助如下:
當使用open函數成功打開一個文件之后,就可以使用read函數讀取文件中的內容,同樣可以使用man指令查詢read函數的用法,如下:
read函數的原型如下:
#includessize_t read(int fd, void *buf, size_t count);
調用 write 函數可向打開的文件寫入數據,通過man 2 write 可以查看該函數的用法,如下:
函數原型如下:
#includessize_t write(int fd, const void *buf, size_t count);
每個打開的文件,系統都會記錄它的讀寫位置偏移量,也把這個讀寫位置偏移量稱為文件指針,它記錄了文件當前的讀寫位置。
當調用 read()或 write()函數對文件進行讀寫操作時,會從當前讀寫位置偏移量開始進行數據讀寫。
并且這個偏移量是以相對于文件頭部的位置開始偏移的,文件第一個字節數據的位置偏移量為 0。
所以有些時候我們對文件進行操作時是需要知道文件當前的偏移位置在哪里的。又或者說需要從文件的某些位置開始操作時,就需要設置文件指針的偏移,這樣才能讓我們操作到需要操作的文件的位置。
設置文件指針偏移的函數為lseek,它的函數原型如下:
#include#include off_t lseek(int fd, off_t offset, int whence);
函數參數如下:
fd :文件描述符。offset :偏移量,以字節為單位。whence :用于定義參數 offset 偏移量對應的參考值,該參數為下列其中一種: 1)SEEK_SET:讀寫偏移量將指向 offset 字節位置處(從文件頭部開始算); 2)SEEK_CUR:讀寫偏移量將指向當前位置偏移量 + offset 字節位置處,offset 可以為正、也可以為負,如果是正數表示往后偏移,如果是負數則表示往前偏移; 3)SEEK_END:讀寫偏移量將指向文件末尾 + offset 字節位置處,同樣 offset 可以為正、也可以為負,如果是正數表示往后偏移、如果是負數則表示往前偏移。
返回值:
成功將返回從文件頭部開始算起的位置偏移量(字節為單位),也就是當前的讀寫位置;發生錯誤將返回-1。
該函數的使用示例:
1)將讀寫位置移動到文件開頭處:off_t offSet = lseek(fd, 0, SEEK_SET);2)將讀寫位置移動到文件末尾:off_t offSet = lseek(fd, 0, SEEK_END);3)將讀寫位置移動到偏移文件開頭 500 個字節處:off_t offSet = lseek(fd, 500, SEEK_SET);4)獲取當前讀寫位置偏移量:off_t offSet = lseek(fd, 0, SEEK_CUR);
如果一個文件已經執行完操作,以后或者暫時不打算用到,那么這個被打開的文件是需要將其關閉的,文件需要使用時要打開,不再使用時要關閉,這是一種編程的習慣,平時也是需要去注意養成的。
關閉文件可以使用close,該函數的原型如下:
#includeint close(int fd);
函數參數和返回值如下:
fd :文件描述符,需要關閉的文件所對應的文件描述符。返回值:如果成功返回 0,如果失敗則返回-1。
注意:close 函數是用于顯式關閉文件的,在 Linux 系統中,如果一個進程終止了,內核會自動關閉這個進程打開的所有文件,這是一種隱式的關閉文件的方式。
?
?