1、stat、fstat、lstat函數
本章討論的中心是三個stat函數以及他們所返回的信息。
#include<sys/stat.h>
int stat(const char * restrict pathname, struct stat *restrict buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *estrict pathname, struct stat *restrict buf);
這三個函數都是返回與指定文件有關的信息。信息保存在struct stat結構中。fstat函數獲取已在描述符filedes上打開文件的有關信息。lstat函數類似於stat,但當命名文件是一個符號鏈接時,它返回的只是該符號鏈接的有關信息而不是符號鏈接所指文件的信息。
struct stat 結構的定義如下:struct stat {
dev_t st_dev; //文件的設備編號
ino_t st_ino; //節點
mode_t st_mode; //文件的類型和存取的權限
nlink_t st_nlink; //連到該文件的硬連接數目,剛建立的文件值爲1
uid_t st_uid; //用戶ID
gid_t st_gid; //組ID
dev_t st_rdev; //(設備類型)若此文件爲設備文件,則爲其設備編號
off_t st_size; //文件字節數(文件大小)
unsigned long st_blksize; //塊大小(文件系統的I/O 緩衝區大小)
unsigned long st_blocks; //塊數
time_t st_atime; //最後一次訪問時間
time_t st_mtime; //最後一次修改時間
time_t st_ctime; //最後一次改變時間(指屬性)
};
2、文件類型
unix的文件類型包括如下幾種
(1)普通文件,最常用的文件類型
(2)目錄文件
(3)特殊塊文件。這種文件類型提供對設備(例如磁盤)帶緩衝訪問,每次訪問以固定長度爲單位進行
(4)字符特殊文件
(5)FIFO管道,主要用於進程間通信
(6)套接字
(7)符號鏈接
文件類型信息包含在st_mode中,可用下表中的宏確定文件類型。
宏 |
文件類型 |
S_ISREG |
普通文件 |
S_ISDIR |
目錄文件 |
S_ISCHR |
字符特殊文件 |
S_ISBLK |
塊特殊文件 |
S_ISFIFO |
管道或FIFO |
S_ISLNK |
符號鏈接 |
S_ISSOCK |
套接字 |
例如 :判斷文件類型是不是普通文件
S_ISREG(buf.st_mode)。
3、設置用戶ID和設置組ID
實際用戶ID:表示我們實際上是誰。
實際組ID:實際上屬於哪一個組
有效用戶ID:決定了我們的文件訪問權限,通常是實際用戶ID
設置用戶ID:將有效用戶ID設置成進程所有者的ID,有效ID就成了設置用戶ID
4、文件訪問權限
用戶指的是文件所有者,有三類u表示用戶,g表示組,o表示其他,這三類訪問權限如下:
st_mode |
意義 |
S_IRUSR |
用戶-讀 |
S_IWUSR |
用戶-寫 |
S_IXUSR |
用戶-執行 |
S_IRGRP |
組-讀 |
S_IWGRP |
組-寫 |
S_IXGRP |
組-執行 |
S_IROTH |
其他-讀 |
S_IWOTH |
其他-寫 |
S_IXOTH |
其他-執行 |
|
|
5、access函數
例如當用open函數打開一個文件時,內核以進程的有效用戶ID和有效組ID爲基礎進行其訪問權限測試,access函數完成了這一功能
#include<unistd.h>
int access(const char *pathname, int mode);成功返回0,出錯返回-1
mode是下表中的常量的按位或
mode |
說明 |
R_OK |
測試讀權限 |
W_OK |
測試寫權限 |
X_OK |
測試執行權限 |
F_OK |
測試文件是否存在 |
6、umask函數
此函數爲進程設置文件模式創建屏蔽字,並返回以前的值。
7、chmod和fchmod函數
這兩個函數用來改變文件的訪問權限
#include<sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int filedes, mode_t mode);
成功:返回0,出錯返回-1
區別:chmod函數在指定的文件上進行操作,而fchmod函數則對已打開的文件進行操作。
改變文件權限的時候,進程的有效用戶ID必須等於文件的所有者ID,或者該進程擁有超級用戶權限。
這兩個函數只是更改i節點最後的更改時間,而不是文件內容的更改時間。
8、chown,fchown,lchown函數
#include<unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int filedes, uid_t owner, gid_t group);
int lchown(const char*pathname, uid_t owner, gid_t group);
這三個函數用來改變文件的用戶ID和組ID
成功返回0,出錯返回-1
注意:如果文件是符號鏈接,lchown只更改符號鏈接本身而不是符號鏈接所指的文件。
9、文件長度
stat結構成員st_size表示以字節爲單位的文件長度,
注意:此字段只對普通文件、目錄文件和符號鏈接有意義。
再注意:對於符號鏈接,文件的長度是文件名中實際的字節數。
例如 lib -> usr/lib,文件長度是7
10、文件中的空洞
空洞是由所設置的偏移量超過文件尾端,並寫某些數據後造成的。
如果使用應用程序(例如cat)複製這種文件,那麼這些空洞會被填滿,被寫爲0,
注意:使用cp時,空洞被過濾掉。
11、文件截斷
#inclue<unistd.h>
int truncate(const char* pathname, off_t length);
int ftruncate(int filedes, off_t length);
成功返回0,出錯返回-1
注意:如果文件長度大於length,超過部分不能再訪問,如果文件長度小於length,一般情況下用0填充。
12、文件系統
目前正在使用的UNIX文件系統有多種實現。例如,SOLARIS支持多種不同類型的磁盤文件系統:傳統的機遇BSD的unix文件系統,ufs,讀寫DOS格式哈軟盤的文件系統,以及讀CD的文件系統。本節討論的是UFS。
我們可以把一個磁盤氛圍一個或者多個分區。每個分區可以包含一個文件系統。如下如圖
磁盤、分區和文件系統
關於i節點:
i節點是固定長度的及錄項,它包含文件的大部分信息。如果更仔細的觀察一個柱面組的i點和數據塊部分,則可以看到如下圖所示的情況。
注意:
圖中有兩個目錄項指向同一i節點。每個i節點中都有一個鏈接計數器,其值是指向該i節點的目錄項數。只有當鏈接數減少至0時,纔可以刪除該文件,有點類似於c++中的智能指針。
每個文件系統各自對他們的i節點進行編號,因此目錄項中i節點編號數指向同一文件系統的相應的i節點,不能使一個目錄項指向另一個文件系統的i節點。這就是硬鏈接不能跨文件系統的原因所在。
在不更換文件系統的情況下爲一個文件更名時,該文件的實際內容並未移動,只需要構造一個指向現有i節點的新目錄項,並解除與舊目錄項的鏈接。例如將文件/usr/lib/foo更名爲/usr/foo時,如果他們在同一文件系統中,文件foo的內容無需移動。