歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> Linux/Unix inode、vnode、dentry、file、進程表、文件表(中)

Linux/Unix inode、vnode、dentry、file、進程表、文件表(中)

日期:2017/3/3 13:40:32   编辑:Linux技術
般我們講,都說進程有文件描述符表,文件描述符表中的指針指向某個inode,這中間省略了file,dentry對象,對准確理解VFS結構無益,本文結合網絡所查,並根據APUE8.3和LKD13.11章節校對,總結在下,希望有用。  
 內核中,對應於每個進程都有一個文件描述符表,表示這個進程打開的所有文件。文件描述表中每一項都是一個指針,指向一個用於描述打開的文件的數據塊———file對象,file對象中描述了文件的打開模式,讀寫位置等重要信息,當進程打開一個文件時,內核就會創建一個新的file對象。需要注意的是,file對象不是專屬於某個進程的,不同進程的文件描述符表中的指針可以指向相同的file對象,從而共享這個打開的文件。file對象有引用計數,記錄了引用這個對象的文件描述符個數,只有當引用計數為0時,內核才銷毀file對象,因此某個進程關閉文件,不影響與之共享同一個file對象的進程.
  file對象中包含一個指針,指向dentry對象。dentry對象代表一個獨立的文件路徑,如果一個文件路徑被打開多次,那麼會建立多個file對象,但它們都指向同一個dentry對象。
  dentry對象中又包含一個指向inode對象的指針。inode對象代表一個獨立文件。因為存在硬鏈接與符號鏈接,因此不同的dentry對象可以指向相同的inode對象.inode 對象包含了最終對文件進行操作所需的所有信息,如文件系統類型、文件的操作方法、文件的權限、訪問日期等。
  打開文件後,進程得到的文件描述符實質上就是文件描述符表的下標,內核根據這個下標值去訪問相應的文件對象,從而實現對文件的操作。

  注意,同一個進程多次打開同一個文件時,內核會創建多個file對象。
  當進程使用fork系統調用創建一個子進程後,子進程將繼承父進程的文件描述符表,因此在父進程中打開的文件可以在子進程中用同一個描述符訪問。

在Linux中,進程是通過文件描述符(file
descriptors,簡稱fd)而不是文件名來訪問文件的,文件描述符實際上是一個整數。Linux中規定每個進程能最多能同時使用NR_OPEN個文件描述符,這個值在fs.h中定義,為1024*1024(2.0版中僅定義為256)。 fd是文件描述符表的索引!!!
每個文件都有一個32位的數字來表示下一個讀寫的 字節位置,這個數字叫做文件位置。每次打開一個文件,除非明確要求,否則文件位置都被置為0,即文件的開始處,此後的讀或寫操作都將從文件的開始處執行, 但你可以通過執行系統調用LSEEK(隨機存儲)對這個文件位置進行修改。Linux中專門用了一個數據結構file來保存打開文件的文件位置,這個結構 稱為打開的文件描述(open
file description)。這個數據結構的設置是煞費苦心的,因為它與進程的聯系非常緊密,可以說這是VFS中一個比較難於理解的數據結構。
file結構中主要保存了文件位置,此外,還把指向該文件索引節點的指針也放在其中。file結構形成一個雙鏈表,稱為系統打開文件表,其最大長度是NR_FILE,在fs.h中定義為8192。
file結構在include\linux\fs.h中定義如下:
[cpp] view
plaincopy
struct file
{
struct list_head f_list;
struct dentry *f_dentry;
struct vfsmount *f_vfsmnt;
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;
unsigned int f_uid, f_gid;
int f_error;
unsigned long f_version;
void *private_data;
};
inode 或i節點是指對文件的索引。如一個系統,所有文件是放在磁盤或flash上,就要編個目錄來說明每個文件在什麼地方,有什麼屬性,及大小等。就像書本的目錄一樣,便於查找和管理。這目錄是操作系統需要的,用來找文件或叫管理文件。許多操作系統都用到這個概念,如linux, 某些嵌入式文件系統等。當然,對某個系統來說,有許多i節點。所以對i節點本身也是要進行管理的。
在linux中,內核通過inode來找到每個文件,但一個文件可以被許多用戶同時打開或一個用戶同時打開多次。這就有一個問題,如何管理文件的當前位移量,因為可能每個用戶打開文件後進行的操作都不一樣,這樣文件位移量也不同,當然還有其他的一些問題。所以linux又搞了一個文件描述符(file descriptor)這個東西,來分別為每一個用戶服務。每個用戶每次打開一個文件,就產生一個文件描述符,多次打開就產生多個文件描述符,一一對應,不管是同一個用戶,還是多個用戶。該文件描述符就記錄了當前打開的文件的偏移量等數據。所以一個i節點可以有0個或多個文件描述符。多個文件描述符可以對應一個i節點。
struct inode {
  struct list_headi_hash;
  struct list_headi_list;
  struct list_headi_dentry;
  struct list_headi_dirty_buffers;
  unsigned longi_ino;
  atomic_t i_count;
  kdev_t i_dev;
  umode_t i_mode;
  nlink_t i_nlink;
  uid_t i_uid;
  gid_t i_gid;
  kdev_t i_rdev;
  off_t i_size;
  time_t i_atime;
  time_t i_mtime;
  time_t i_ctime;
  unsigned long i_blksize;
  unsigned long i_blocks;
  unsigned long i_version;
  unsigned short i_bytes;
  struct semaphore i_sem;
  struct rw_semaphore i_truncate_sem;
  struct semaphore i_zombie;
  struct inode_operations *i_op;
  struct file_operations *i_fop;
  struct super_block *i_sb;
  wait_queue_head_t i_wait;
  struct file_lock *i_flock;
  struct address_space *i_mapping;
  struct address_space i_data;
  struct dquot *i_dquot [MAXQUOTAS];
  
  struct pipe_inode_info *i_pipe;
  struct block_device *i_bdev;
  struct char_device *i_cdev;
  unsigned longi_dnotify_mask;
  struct dnotify_struct *i_dnotify;
  unsigned long i_state;
  unsigned int i_flags;
  unsigned char i_sock;
  atomic_t i_write count;
  unsigned int i_attr_flags;
  __u32 i_generation;
  union {
  struct minix_inode_info minix_i;
  struct ext2_inode_info ext2_i;
  struct ext3_inode_info ext3_i;
  struct hpfs_inode_info hpfs_i;
  struct ntfs_inode_info ntfs_i;
  struct msdos_inode_info msdos_i;
  struct umsdos_inode_info umsdos_i;
  struct iso_inode_info isofs_i;
  struct sysv_inode_info sysv_i;
  struct affs_inode_info affs_i;
  struct ufs_inode_info ufs_i;
  struct efs_inode_info efs_i;
  struct romfs_inode_info romfs_i;
  struct shmem_inode_info shmem_i;
  struct coda_inode_info coda_i;
  struct smb_inode_info smbfs_i;
  struct hfs_inode_info hfs_i;
  struct adfs_inode_info adfs_i;
  struct qnx4_inode_info qnx4_i;
  struct reiserfs_inode_info reiserfs_i;
  struct bfs_inode_info bfs_i;
  struct udf_inode_info udf_i;
  struct ncp_inode_info ncpfs_i;
  struct proc_inode_info proc_i;
  struct socketsocket_i;
  struct usbdev_inode_info usbdev_i;
  struct jffs2_inode_infojffs2_i;
  void *generic_ip;
  } u;
  };
  關於vnode節點,是VFS一部分,我還沒來得及查證,但是如MOS(《現代操作系統》)10.6.4節所說,vnode用以識別inode是本地還是遠程的,屬於NFS的思想。日後再補。
/content/3973546.html
http://blog.chinaunix.net/uid-23123869-id-3402064.html
Copyright © Linux教程網 All Rights Reserved