您的位置:首页 > 运维架构 > Linux

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

2016-05-07 14:49 771 查看
般我们讲,都说进程有文件描述符表,文件描述符表中的指针指向某个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的思想。日后再补。

/article/5050586.html

http://blog.chinaunix.net/uid-23123869-id-3402064.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: