一張表圖:
這張圖描述的是進程級別的文件描述符和系統級別的打開文件表和系統級別的文件系統索引結點的連繫關係。
由圖可以知道:
- 每個進程維護的文件描述符表文件描述符從零開始, 進程間的文件描述符編號會重複;
- 打開文件表中的打開文件句柄可以對應同一個進程的多個文件描述符(dup dup2 fcntl效果),或者是不同進程間的多個文件描述符(例如父子進程的繼承關係);
- 不同的打開文件表的打開文件句柄可能對應着同一個實體文件,可能是多次打開的效果。
文件描述符:
文件描述符是爲了高效管理已經被打開的文件的所有i/o操作的系統調用所創建的索引,通常爲大於等於0的整數。
操作系統爲每個進程維護一個文件描述符表,表內的值都是從0開始遞增,每個文件描述符對應一個打開的文件。所以不同的文件描述符可能對應同一個打開的文件,相同的描述符可能對應着不同的文件。
打開文件表
操作系統爲在系統中打開的所有文件使用一個叫做打開文件表 的結構進行維護,表格中的每條記錄稱爲打開文件句柄 。文件句柄記錄了打開的文件的所有相關信息。
結構結點的信息:
struct file
{
struct list_head f_list; /*所有打開的文件形成一個鏈表*/
struct dentry *f_dentry;
/*指向相關目錄項的指針(對象結點包含一個指向inode結點的對象指針)*/
struct vfsmount *f_vfsmnt; /*指向VFS安裝點的指針*/
struct file_operations *f_op; /*指向文件操作表的指針*/
mode_t f_mode; /*文件的打開模式*/
loff_t f_pos; /*文件的當前位置*/
unsigned short f_flags; /*打開文件時所指定的標誌*/
unsigned short f_count; /*使用該結構的進程數(引用計數)*/
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
/*預讀標誌、要預讀的最多頁面數、上次預讀後的文件指針、預讀的字節數以及預讀的頁面數*/
int f_owner; /* 通過信號進行異步I/O數據的傳送*/
unsigned int f_uid, f_gid; /*用戶的UID和GID*/
int f_error; /*網絡寫操作的錯誤碼*/
unsigned long f_version; /*版本號*/
void *private_data; /* tty驅動程序所需 */
};
文件系統索引結點
index node (inode結點)
見:http://blog.csdn.net/danneel/article/details/47067301
由於文件索引有硬鏈接和軟連接之分,所以,不同的打開文件句柄可能指向的是同一個物理文件。
dup
int dup(int oldfd);
系統將自動使用未被使用的最小文件描述符作爲從定向的目標句柄,oldfd是重定向的源句柄。
dup2
int dup2(int oldfd, int newfd);
指定一個新的文件描述符newfd作爲從定向的目標句柄, 如果newfd早已經被打開, 則將其掛關閉;如果兩者相同,不關閉,返回newfd。
fcntl
fcntl函數針對文件描述符提供控制, 它的功能有以下幾種:
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或F_SETLKW).
其中功能1 實現的功能與dup dup2相似, 只是形式不一樣:
dup(oldfd);
~
fcntl(oldfd, F_DUPFD, 0);
dup2(oldfd, newfd);
~
fcntl(oldfd, F_DUPFD, newfd);
all