文章目錄
Linux 下的檔案操作
1. 使用系統調用
Linux提供了一些系統調用(System Call) 來進行檔案操作,包括:open, read, write, close, lseek, ioctl, etc. (PS:系統調用可以使用組合語言調用)
其他所有系統調用都定義在 unistd.h 中,只有open找不到,用下面的代碼試了一下:
int main(){ int fd; fd = open("file.c", 2); printf("file descriptor is : %d.\n", fd); return 0;}
GCC(4.6.1)直接編譯通過,只給了個warning: implicit declaration of function 'open', 奇怪的是printf也不用標頭檔,程式運行正常。哪位大俠知道指點下吧:)
open的原型定義為:
int open (const char *filename, int flags[, mode_t mode])
其中第二個參數常用的有:O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, 都在 fcntl.h 中定義為宏, 大家不要像上面例子中那樣傳參。第三個參數可選,只有在建立檔案的時候(第二個參數有O_CREAT)才有用。給個例子:
open ("myfile", O_CREAT, S_IRUSR|S_IXUSR|S_IROTH);
建立並開啟檔案myfile,設定許可權為自己可讀可執行(S_IRUSR|S_IXUSR),其他人可讀(S_IROTH)。
參數很多,我也沒用全,大家在自己使用的時候慢慢摸索吧,這裡略了。
2. 使用庫函數
檔案操作除了使用系統調用,還可以使用程式設計語言提供的庫函數(library function)。比如C的標準輸入輸出庫:stdio.h 提供了以下一些函數:fopen, fread, fwrite, fclose, fflush fseek, etc. (PS: 其實彙編也可以調用這些函數)
這些庫函數是更進階的抽象,使用了流(stream)的概念,內部使用了緩衝,所以雖然庫函數最終還是使用了系統調用實現自己的功能,但是比我們自己直接使用系統調用要方便,也要更高效。寫起來方便寫寫就知道了,為什麼調用起來效率低呢?寫個測試也可以比出來,究其原因是因為系統調用是核心態的函數,每次調用核心都要從使用者態切到核心態,更主要的是庫函數內部的緩衝,可以減少系統調用的次數,同樣100次輸出,寫成系統調用就是赤裸裸的100次系統調用,相當慢;而寫成庫函數就可能被內部緩衝儲存起來調用一次系統調用輸出,一次哦,效率當然也就快了。
但是一些特殊情況下只能使用系統調用,比如編寫驅動程式,使用特殊的輸入輸出控制等等。
最後給個庫函數開啟檔案的例子:
FILE *in;in = fopen("file.in", "r");
以唯讀方式開啟名為 file.in 的檔案。fopen的聲明如下:
FILE *fopen(const char *filename, const char *mode);
返回一個FILE的指標,FILE是個結構體,stdio.h裡面有個聲明:
/* Define outside of namespace so the C++ is happy. */struct _IO_FILE;typedef struct _IO_FILE FILE;
注釋很歡樂,真正的結構體_IO_FILE定義在libio.h 裡面,感興趣可以自己去看看。
其中mode可以為:
"r" or "rb": Open for reading only
"w" or "wb": Open for writing, truncate to zero length
"a" or "ab": Open for writing, append to end of file
"r+" or "rb+" or "r+b": Open for update (reading and writing)
"w+" or "wb+" or "w+b": Open for update, truncate to zero length
"a+" or "ab+" or "a+b": Open for update, append to end of file
b表示開啟一個二進位檔案(binary file)。預設則開啟文字檔。
Reference:
Beginning Linux Programming, 4th Edition by Neil Matthew, Richard Stones.
The GNU C library, chapter 13.