"In Linux, everything is a file." --- <<Beginning Linux Programming>>
3個主要的檔案描述符:
0: 標準輸入
1: 標準輸出
2: 標準錯誤
基本檔案操作
write:
函式宣告:ssize_t write(int fildes, const void *buf, size_t nbytes);
函數功能:把從buf開始的nbytes個位元組寫入描述符為fildes所關聯的檔案中。
傳回值: 返回實際寫入的位元組數。傳回值可能小於nbytes。如果返回0則
沒有資料寫入;如果返回-1則表示有錯誤發生。
read:
函式宣告:ssize_t read(int fildes, void *buf, size_t nbytes);
函數功能:把描述符為fildes所關聯的檔案中的nbytes個位元組寫入buf中。
傳回值: 返回實際讀入的位元組數,可能小於nbytes。如果返回0則表示
沒有資料讀入;如果返回-1則表示有錯誤發生。
open:
函式宣告:int open(const char *path, int oflags);
int open(const char *path, int oflags, mode_t mode);
函數功能:以oflags為存模數式,開啟path所指向的檔案,返回該檔案的檔案
描述符。oflags可以是:(其他值請參考 man 2 open)
O_RDONLY 唯讀
O_WRONLY 唯寫
O_RDWR 讀和寫
O_APPEND 在檔案的末尾添加
O_TRUNC 丟棄已經存在的內容,將檔案長度置0
O_CREAT 建立檔案,可以用mode參數指明許可權
這些值可以用“或”操作串連起來,如:O_CREAT|O_WRONLY|O_TRUNC。
mode參數可以設定建立檔案的存取權限:
S_IRUSR 讀,檔案所有者
S_IWUSR 寫,檔案所有者
S_IXUSR 執行,檔案所有者
S_IRGRP 讀,檔案所有者所在的組
S_IWGRP 寫,檔案所有者所在的組
S_IXGRP 執行,檔案所有者所在的組
S_IROTH 讀,其他人
S_IWOTH 寫,其他人
S_IXOTH 執行,其他人
mode參數也可以用“或”串連,如open("myfile",O_CREAT,S_IRUSR|S_IXOTH),
則檔案myfile的許可權為-r-------x。
傳回值: 檔案描述符(非負整數),如果失敗則返回-1。
close:
函式宣告:int close(int fildes);
函數功能:關閉檔案描述符。
傳回值: 0表示成功,-1表示失敗。
ioctl:
函式宣告:int ioctl(int fildes, int cmd, ...);
函數功能:向裝置寫入控制資訊。
傳回值: -1表示出錯。
例子:
#include <unistd.h><br />#include <sys/stat.h><br />#include <fcntl.h><br />#include <stdlib.h><br />int main()<br />{<br /> char block[1024];<br /> int in, out;<br /> int nread;<br /> in = open(“file.in”, O_RDONLY);<br /> out = open(“file.out”, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);<br /> while((nread = read(in,block,sizeof(block))) > 0)<br /> write(out,block,nread);<br /> exit(0);<br />}
lseek:
函式宣告:off_t lseek(int fildes, off_t offset, int whence);
函數功能:對檔案描述符fildes設定讀寫位置。offset設定讀寫位置,
whence設定offset如何用。whence可以為如下值:
SEEK_SET offset為絕對位置(檔案開始的相對位置)
SEEK_CUR offset為當前位置的相對位置
SEEK_END offset為檔案結尾的相對位置
傳回值: 檔案指標相對於檔案開始的位置。
fstat, stat, and lstat:
函式宣告:int fstat(int fildes, struct stat *buf);
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
函數功能:fstat返迴文件描述符fildes所關聯檔案的資訊;stat、lstat
返回已命名檔案的資訊;如果是符號連結,lstat返回符號
連結本身的資訊,而stat則返回符號連結所引用檔案的資訊。
所返回的檔案資訊儲存在結構體指標buf所指向的空間中。
關於結構體stat的資訊請參閱man 2 stat。
傳回值: 如果成功則返回0,否則返回-1。
dup and dup2:
函式宣告:int dup(int fildes);
int dup2(int fildes, int fildes2);
函數功能:返回不同的檔案描述符訪問同一個檔案。dup返回fildes
所關聯檔案的一個新檔案描述符;dup2建立fildes的一個
副本。它們通常用於讀寫同一個檔案的不同位置,也用於
多個進程通過管道進行通訊。
傳回值: 如果出錯則返回-1。
標準I/O庫
參見C語言教程。
檔案流和檔案描述符
每一個檔案流都和底層的一個檔案描述符相關聯,你能混合使用它們。
int fileno(FILE *stream);
FILE *fdopen(int fildes, const char *mode);
fileno返迴文件檔案流stream的檔案描述符,如果出錯則返回-1;
fdopen為檔案描述符fildes建立檔案流。fildes必須為已開啟的。
fdopen和fopen除了第一個參數不一樣,其他都一樣。
檔案和目錄的維護
改變許可權:int chmod(const char *path, mode_t mode);
改變所有者:int chown(const char *path, uid_t owner, gid_t group);
unlink, link, and symlink:
函式宣告:int unlink(const char *path);
int link(const char *path1, const char *path2);
int symlink(const char *path1, const char *path2);
函數功能:unlink刪除目錄下的檔案,如果是永久連結則還將連結數減1.
link建立path2,path2為path1的永久連結。
symlink建立path2,path2為path1的軟連結。
傳回值: 成功返回0,失敗返回-1。
mkdir and rmdir:
函式宣告:int mkdir(const char *path, mode_t mode);
int rmdir(const char *path);
函數功能:mkdir建立許可權為mode的目錄。
rmdir刪除目錄,只有當path為空白目錄時才能刪除。
傳回值: 成功返回0,失敗返回-1。
chdir and getcwd:
函式宣告:int chdir(const char *path);
char *getcwd(char *buf, size_t size);
函數功能:chdir改變程式啟動並執行的目前的目錄。
把程式啟動並執行目前的目錄寫入buf,目錄名的長度不能超過size。
傳回值: 成功返回0,失敗返回-1。
掃描目錄
用DIR結構對目錄操作,DIR*稱為目錄流(如同FILE*稱為檔案流一樣)
opendir
函式宣告:DIR *opendir(const char *name);
函數功能:opendir開啟一個目錄。
傳回值: 成功則返回一個DIR結構的指標,失敗返回NULL。
readir
函式宣告:struct dirent *readdir(DIR *dirp);
函數功能:在dirp中返回下一個目錄入口。
傳回值: 目錄入口資訊(man dirent)。如果出錯或到達目錄結尾,
則返回NULL。
telldir
函式宣告:long telldir(DIR *dirp);
函數功能:返回目錄流dirp中的當前位置。
傳回值:
seekdir
函式宣告:void seekdir(DIR *dirp, long loc);
函數功能:設定dirp中的目錄入口指標,loc表示指標的位置。
傳回值: 無
closedir
函式宣告:int closedir(DIR *dirp);
函數功能:關閉目錄流。
傳回值: 成功返回0,失敗返回-1。
例子:
#include <unistd.h><br />#include <stdio.h><br />#include <dirent.h><br />#include <string.h><br />#include <sys/stat.h><br />#include <stdlib.h><br />void printdir(char *dir, int depth)<br />{<br /> DIR *dp;<br /> struct dirent *entry;<br /> struct stat statbuf;<br /> if((dp = opendir(dir)) == NULL) {<br /> fprintf(stderr,"cannot open directory: %s/n", dir);<br /> return;<br /> }<br /> chdir(dir);<br /> while((entry = readdir(dp)) != NULL) {<br /> lstat(entry->d_name,&statbuf);<br /> if(S_ISDIR(statbuf.st_mode)) {<br /> /* Found a directory, but ignore . and .. */<br /> if(strcmp(".",entry->d_name) == 0 ||<br /> strcmp("..",entry->d_name) == 0)<br /> continue;<br /> printf("%*s%s//n",depth,"",entry->d_name);<br /> /* Recurse at a new indent level */<br /> printdir(entry->d_name,depth+4);<br /> }<br /> else printf("%*s%s/n",depth,"",entry->d_name);<br /> }<br /> chdir("..");<br /> closedir(dp);<br />}<br />int main()<br />{<br /> printf("Directory scan of /usr:/n");<br /> printdir("/usr",0);<br /> printf("done./n");<br /> exit(0);<br />}
進階話題
記憶體映射函數(mmap)設定一段記憶體空間,這段空間可以被多個程式讀寫。
mmap也可以用來操作檔案,它可以使檔案的整個內容看起來像記憶體中的數組一樣。
函式宣告:void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
函數功能:(man mmap)fildes為檔案描述符;off指定映射的檔案的起始位置;len指定要
映射的長度(也就是記憶體段的長度);prot指定這段記憶體的
存取許可權,prot可為以下值(可以用or串連):
PROT_READ 可讀
PROT_WRITE 可寫
PROT_EXEC 可執行
PROT_NONE 該記憶體段不能存取
flags設定這段記憶體的控制資訊,MAP_PRIVATE為私人的,MAP_SHARED為共用的。
MAP_SHARED可以使對這段記憶體的修改反映到檔案中。addr指定這段記憶體空間的
起始地址,如果為0則由系統自動分配(推薦)。
傳回值: 如果成功則返回這段記憶體空間的其真實位址,失敗返回MAP_FAILED。