O_RDONLY:只讀方式打開node
O_WRONLY:只寫方式打開編程
O_RDWR:可讀寫方式打開bash
O_CREAT:若路徑中文件不存在則建立,使用Open函數時需同時指定文件權限異步
O_EXCL:若與O_CREAT連用,檢查文件是否已經存在,若不存在則創建文件存在則返回錯誤,這使建立和測試成爲一個原子操做socket
O_APPEND:讀寫文件從文件尾部開始移動,全部寫入數據都加入文件尾部async
O_TRUNC:若文件存在而且能夠寫入,此標識會將源文件內容清空ide
O_NONBLOCK:若是打開或建立文件是管道文件,或一個塊特殊文件,一個字符特殊文件,該表示表明後續操做非阻塞函數
S_IRUSR:用戶讀權限測試
S_IWUSR:用戶寫權限ui
S_IXUSR:用戶執行權限
S_IRWX:用戶讀寫執行權限
S_IRGRP:用戶組讀權限
S_IWGRP:用戶組寫權限
S_IXGRP:用戶組執行權限
S_IRWXG:用戶組讀寫執行權限
S_IROTH:其餘用戶讀權限
S_IWOTH:其餘用戶寫權限
S_IXOTH:其餘用戶執行權限
S_IRWXO:其餘用戶讀寫執行權限
S_ISUID:SUID權限
S_ISGID:SGID權限
O_SYNC:每次write都等到物理I/O完成才返回,包括文件屬性更新I/O操做完成
O_DSYNC: 每次write都等到物理I/O完成才返回,不包括文件屬性更新I/O操做完成
O_RSYNC:使每個以文件描述符做爲參數的read的參數等待,直到任何對文件同一部分進行的寫操做都完成
用於打開或建立文件
Int open(文件路徑,標識,權限標識)
文件路徑:絕對路徑與相對路徑都可
標識:文件標識與操做副標識以及文件同步標識的結合結合
權限標識:是使用權限標識,也可用數字法標識
返回值:成功返回文件標識符.出錯返回-1
用於建立文件
int creat(文件路徑, 權限標識)
返回值:成功返回文件標識符.出錯返回-1
說明:以只寫方式打開文件
用於關閉文件,當一個進程終止時,內核會自動關閉它打開的全部文件
int close(int fd)
返回值:成功返回0.出錯返回-1
用於設置文件偏移量
off_tsleek(int fd,off_t offset,int whence)
若whence= SEEK_SET,設置當前偏移量爲距離文件開始處offset字節
若whence= SEEK_CUR,設置當前偏移量爲距離文件當前偏移處offset字節(offset可爲正負)
若whence= SEEK_END,設置當前偏移量爲文件長度加offset(offset可爲正負)
返回值:成功返回新的文件偏移量,失敗返回-1 (對於管道文件不能設置偏移文件,所以返回-1)
複製一個現存的文件描述符
Int dup(intfd)
Int dup(intfd1,int fd2)
Fd1爲複製的文件描述符源
Fd2爲複製的文件描述符目的地
若是fd2文件爲關閉應先關閉
返回值:成功返回新的文件描述符,失敗返回-1
舉例:
#include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <stdio.h> int main() { int f = open("output", O_CREAT | O_TRUNC | O_RDWR, 0644); if (f == -1) { perror("文件建立失敗!"); return 0; } int newf = dup(f); write(f, "往文件裏寫輸入!\n", 25); write(newf, "使用新的文件描述符!\n", 31); int oldInput = dup(STDOUT_FILENO); puts("使用標準輸出到控制檯"); dup2(f, STDOUT_FILENO); puts("使用標準輸出到文件"); dup2(oldInput, STDOUT_FILENO); puts("還原標準輸出到控制檯"); return 0; }
控制檯輸出:
使用標準輸出到控制檯
還原標準輸出到控制檯
output文件內容:
往文件裏寫輸入!
使用新的文件描述符!
使用標準輸出到文件
改變已打開文件的文件性質
int fcntl (int fd, int cmd, ...);
主要功能:
1: 複製一個現有描述符:Cmd=F_DUPFD
2:獲取/設置文件描述符標註cmd= F_GETFD或F_SETFD
3:獲取/設置文件狀態標註 cmd=F_GETFL或F_SETFL
4:獲取/設置異步I/O全部權 cmd= F_GETOWN或F_SETOWN
5:獲取/設置記錄鎖 cmd= F_GETLK或F_SETLK
Fcntl的文件狀態標識
O_RDONLY
O_WRONLY
O_RDWR
O_APPENT
O_NONBLOCK
O_SYNC
O_DSYNC
O_FSYNC
說明:
1:因爲 O_RDONLY,O_WRONLY,O_RDWR 只能同時存在一個,所以須要用O_ACCMODE取得訪問屏蔽位
2:F_SETFL只能設置O_APPENT,O_NONBLOCK,O_SYNC,O_DSYNC,O_FSYNC
舉例:
#include <stdio.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char *argv[]) { int fd = open("fcnt", O_RDWR | O_APPEND|O_SYNC ); printf("文件描述符=%d\n", fd); int flag = fcntl(fd, F_GETFL, 0); switch (flag & O_ACCMODE) { case O_RDWR: printf("O_RDWR\n"); break; case O_RDONLY: printf("O_RDONLY\n"); break; case O_WRONLY: printf("O_WRONLY\n"); break; default: printf("default\n"); break; } if (flag & O_APPEND) { printf("O_APPEND\n"); } #if defined (O_SYNC) if (flag & O_SYNC) { printf("O_SYNC\n"); } #endif if (flag & O_NONBLOCK) { printf("O_NONBLOCK\n"); } close(1); fcntl(fd,F_DUPFD,1); puts("經過標準輸出寫到文件\n"); return 0; }
控制檯輸出
文件描述符=3
O_RDWR
O_APPEND
O_SYNC
當數據寫入文件時,內核一般先將數據複製到一個緩衝區中,若是該緩衝區還沒有寫滿,則不將其排入輸出隊裏,直到其寫滿或者內核須要使用這塊緩衝區作其餘使用,這種方式叫作延遲寫
好處是,能夠減小IO操做,可是帶來的風險就是系統發生故障時,會形成數據的丟失
總結起來,數據寫入文件分爲如下3步:
1.寫入緩衝區
2.緩衝區數據排入輸出隊裏
3.將緩衝區數據寫入磁盤
void sync (void)
將緩衝區排入輸出隊裏後返回
int fsync (int __fd);
等待數據寫入磁盤而且文件屬性更新後返回
int fdatasync (int __fildes);
等待數據寫入磁盤返回
測試實際用戶是否有相應權限
int access (constchar *name, int mode)
mode:
R_OK:測試讀權限
W_OK:測試寫權限
X_OK:測試執行權限
F_OK:測試文件是否存在
文件連接分爲2種狀況
1.硬連接:不會產生新的INODE,IBLOCK,只是在原有數據鏈接數上+1
不能跨文件系統使用
硬連接目錄須要ROOT權限
2.軟連接:產生的INODE,IBLOCK,新的IBLOCK記錄連接的內容
能夠跨文件系統使用
對於軟連接來講,有些函數時直接做用連接文件自己,有些函數則跟隨源文件連接到源文件
函數 |
不跟隨符號連接 |
跟隨符號連接 |
access |
√ |
|
chdir |
√ |
|
chmod |
√ |
|
chown |
√ |
√ |
creat |
√ |
|
exec |
√ |
|
lchown |
√ |
|
link |
√ |
|
lstat |
√ |
|
open |
√ |
|
opendir |
√ |
|
pathconf |
√ |
|
readlink |
√ |
|
remove |
√ |
|
rename |
√ |
|
stat |
√ |
|
truncate |
√ |
|
unlink |
√ |
建立文件的硬連接
int link (constchar *__from, constchar *__to)
刪除一個文件
int unlink (constchar *__name)
說明:對於硬連接來講unlink只是刪除文件連接符,文件實際數據的鏈接數-1,若是爲文件實際數據0則在全部進程關閉對此文件鏈接時刪除
舉例
#include <unistd.h> #include <stdio.h> #include <fcntl.h> #define BUFFER_SIZE 409600 int printfilestat(int fd, struct stat *buf) { int results = fstat(fd, buf); if (results == -1) { perror("文件屬性獲取失敗"); return -1; } printf("文件鏈接數是=%d\n", buf->st_nlink); return 0; } int main() { int fd = open("linkfile", O_RDWR, 0777); if (fd == -1) { perror("文件打開失敗"); return -1; } struct stat buf; printfilestat(fd, &buf); if (link("linkfile", "newlinkfile") == 0) { puts("連接文件建立成功"); } printfilestat(fd, &buf); if (unlink("newlinkfile") == 0) { puts("newlinkfile文件刪除成功"); } printfilestat(fd, &buf); if (unlink("linkfile") == 0) { puts("linkfile文件刪除成功"); } printfilestat(fd, &buf); sleep(30); close(fd); puts("關閉文件!"); sleep(-1); return 0; }
控制檯輸出
文件鏈接數是=1
連接文件建立成功
文件鏈接數是=2
newlinkfile文件刪除成功
文件鏈接數是=1
linkfile文件刪除成功
文件鏈接數是=0
è雖然文件鏈接數爲0 可是文件數據沒有被刪除,須要等待全部進程都close該文件纔會被從磁盤刪除
tkf@tkf:~/workspace/FileOperator$ ll linkfile ;df ./
-rwxrwxr-x 1 tkf tkf 4096005月9 16:34linkfile*
文件系統1K-blocks已用可用已用% 掛載點
/dev/sda128768380 17972780931121266% /
執行程序
tkf@tkf:~/workspace/FileOperator$ df ./
文件系統1K-blocks已用可用已用% 掛載點
/dev/sda128768380 17972784931120866% /
linkfile, newlinkfile文件符號鏈接刪除,所以可用資源變多了
sleep(30)
tkf@tkf:~/workspace/FileOperator$df ./
文件系統1K-blocks已用可用已用% 掛載點
/dev/sda128768380 17972344931164866% /
執行了close,所以在無進程來接到數據,因此文件數據被釋放,可用資源再一次變多了
建立一個軟連接
int symlink (constchar *__from, constchar *__to)
返回值:成功返回0,失敗返回-1
打開軟連接文件
ssize_t readlink (constchar *__restrict __path,
char *__restrict __buf, size_t __len)
返回值:成功返回0,失敗返回-1
Int fstat(文件標識符,struct stat *buf)
Int lstat(文件路徑,struct stat *buf)
Int stat(文件路徑,struct stat *buf)
文件路徑:絕對路徑與相對路徑都可
文件標識符:文件建立或打開時返回的文件標示符
struct stat *buf:文件屬性結構體
返回值:成功返回0,失敗返回-1
說明:stat和lstat的區別:當文件是一個符號連接時,lstat返回的是該符號連接自己的信息;而stat返回的是該連接指向的文件的信息
struct stat {
dev_t st_dev; 文件所在設備的ID
ino_t st_ino; 與該文件關聯的inode
mode_t st_mode;
nlink_t st_nlink; /* 鏈向此文件的鏈接數(硬鏈接)*/
uid_t st_uid; 文件屬主的UID號
gid_t st_gid; 文件屬主的GID號
dev_t st_rdev; 設備號,針對設備文件
off_t st_size; 文件大小
blksize_t st_blksize; 系統塊的大小(IO緩衝區適合大小)
blkcnt_t st_blocks; 文件所佔塊數
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
}
文件類型標誌:
S_IFBLK:文件是一個特殊的塊設備
S_IFDIR:文件是一個目錄
S_IFCHR:文件是一個特殊的字符設備
S_IFIFO:文件是一個FIFO設備
S_IFREG:文件是一個普通文件(REG即便regular啦)
S_IFLNK:文件是一個符號連接
其餘模式標誌:
S_ISUID: 文件設置了SUID位
S_ISGID:文件設置了SGID位
S_ISVTX:文件設置了SBIT位
用於解釋st_mode標誌的掩碼:
S_IFMT:文件類型
S_IRWXU:屬主的讀/寫/執行權限,能夠分紅S_IXUSR,S_IRUSR, S_IWUSR
S_IRWXG:屬組的讀/寫/執行權限,能夠分紅S_IXGRP,S_IRGRP, S_IWGRP
S_IRWXO:其餘用戶的讀/寫/執行權限,能夠分爲S_IXOTH,S_IROTH, S_IWOTH
肯定文件類型
S_ISBLK:測試是不是特殊的塊設備文件
S_ISCHR:測試是不是特殊的字符設備文件
S_ISDIR:測試是不是目錄(我估計find .-type d的源代碼實現中就用到了這個宏)
S_ISFIFO:測試是不是FIFO設備
S_ISREG:測試是不是普通文件
S_ISLNK:測試是不是符號連接
S_ISSOCK:測試是不是socket
設置文件權限屏蔽字
mode_t umask (mode_t __mask)
設置文件權限
int chmod (constchar * file, __mode_tmode)
int lchmod (constchar * file, __mode_tmode)
int fchmod (int fd, mode_tmode)
設置文件所屬用戶及用戶組
int chown (constchar *__file, __uid_t __owner, __gid_t__group)
int fchown (int __fd, __uid_t __owner, __gid_t __group) _
int lchown (constchar *__file, __uid_t __owner, __gid_t __group)
Int mkdir(路徑,權限)
路徑:絕對路徑相對路徑都可
權限:以數字形式表示的權限
返回值:成功返回0,失敗返回-1
Int chdir(路徑)
路徑:絕對路徑相對路徑都可
返回值:成功返回0,失敗返回-1
Int fchdir(intfiledes)
返回值:成功返回0,失敗返回-1
char *getcwd (char *__buf, size_t __size)
返回值:當前工做目錄
打開目錄,得到子目錄流指針
DIR*opendir(char *name)
讀取子目錄
structdirent* readdir((DIR *dirp)
返回子目錄流裏的當前位置
longint telldir(DIR* drip)
設置子目錄流的當前數據項指針
voidseekdir(DIR* drip,long int loc)
關閉子目錄流
DIR*opendir(DIR* drip)
刪除目錄:int rmdir(路徑)
刪除文件:int unlink(路徑)
返回值:成功返回1,失敗返回-1
#include<fcntl.h> #include<sys/stat.h> #include<unistd.h> #include<stdio.h> #include<malloc.h> #include<string.h> #include<dirent.h> #include<stdlib.h> typedefenum { false = 0, true = 1 } bool; voidprintFileInfo(struct stat* buf) { bool userall = false; printf("文件權限是:%o. 詳細信息以下:\n", (buf->st_mode& 0x0fff)); if (buf->st_mode& S_IRWXU) { userall = true; printf("全部者擁有讀寫執行權限\n"); } if (buf->st_mode& S_IRWXG) { printf("用戶組擁有讀寫執行權限\n"); } if (buf->st_mode& S_IRWXO) { printf("其餘人擁有讀寫執行權限\n"); } if (userall) { if (buf->st_mode& S_IRUSR) { printf("全部者擁有讀權限\n"); } if (buf->st_mode& S_IWUSR) { printf("全部者擁有寫權限\n"); } } if (buf->st_mode& S_IFREG) { printf("文件是一個普通文件\n"); } if (buf->st_mode& S_ISUID) { printf("文件設置了SUID權限\n"); } if (buf->st_mode& S_ISGID) { printf("文件設置了GUID權限\n"); } printf("UID=%d\n", buf->st_uid); printf("GID=%d\n", buf->st_gid); printf("佔用block=%ld\n", buf->st_blocks); printf("block大小=%ld\n", buf->st_blksize); printf("最後訪問時間=%ld\n", buf->st_atim.tv_sec); printf("最後狀態更新時間=%ld\n", buf->st_ctim.tv_sec); printf("最後修改時間=%ld\n", buf->st_mtim.tv_sec); } intOpenFile(constchar *fpath) { unlink(fpath); int f = open(fpath, O_RDWR); if (f == -1) { f = creat(fpath, S_IWUSR | S_IRUSR); if (f != -1) { printf("建立一個文件\n"); } else { printf("沒法建立文件\n"); return -1; } } else { printf("文件打開成功\n"); } return f; } voidscan_dir(constchar* dir, int depth) { DIR *dp; struct dirent* entry; if ((dp = opendir(dir)) == NULL) { printf("沒法打開目錄:%s\n", dir); return; } struct stat statbuf; chdir(dir); while ((entry = readdir(dp)) != NULL) { constchar* name = entry->d_name; lstat(name, &statbuf); if (S_IFDIR & statbuf.st_mode) { if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0) { continue; } printf("%*s%s:%o\n", depth, "", entry->d_name, (statbuf.st_mode& 0x0fff)); scan_dir(entry->d_name, depth + 4); } else { printf("%*s%s:%o\n", depth, "", entry->d_name, (statbuf.st_mode& 0x0fff)); } } chdir(".."); closedir(dp); } intmain() { constchar *fpath = "test"; int f = OpenFile(fpath); struct stat *buf = malloc(sizeof(struct stat)); fstat(f, buf); printf("===================================================\n"); printFileInfo(buf); printf("===================================================\n"); close(f); sleep(1); chmod("test", 7777); printf("更改文件權限爲7777\n"); stat("test", buf); printf("===================================================\n"); printFileInfo(buf); printf("===================================================\n"); free(buf); printf("==================掃描文件夾============================\n"); scan_dir("/home", 0); umask(0011); mkdir("/tmp/mydir", 0777); creat("/tmp/mydir/myfile", 0777); printf("==================掃描文件夾==========================\n"); scan_dir("/tmp/mydir", 0); chdir("/tmp"); unlink("mydir/myfile"); rmdir("mydir"); return 0; }
執行結果
建立一個文件
===================================================
文件權限是:600. 詳細信息以下:
全部者擁有讀寫執行權限
全部者擁有讀權限
全部者擁有寫權限
文件是一個普通文件
UID=0
GID=0
佔用block=8
block大小=4096
最後訪問時間=1397539372
最後狀態更新時間=1397539372
最後修改時間=1397539372
===================================================
更改文件權限爲7777
===================================================
文件權限是:7141. 詳細信息以下:
全部者擁有讀寫執行權限
用戶組擁有讀寫執行權限
其餘人擁有讀寫執行權限
文件是一個普通文件
文件設置了SUID權限
文件設置了GUID權限
UID=0
GID=0
佔用block=8
block大小=4096
最後訪問時間=1397539372
最後狀態更新時間=1397539373
最後修改時間=1397539372
===================================================
==================掃描文件夾============================
.bashrc:644
.bash_logout:644
.mozilla:755
extensions:755
plugins:755
.nautilus:755
metafiles:700
目錄建立成功
文件建立成功
==================掃描文件夾==========================
myfile:766
文件刪除成功
目錄刪除成功