当前位置: 首页 > news >正文

广东网站备案进度查询莱芜雪野湖介绍

广东网站备案进度查询,莱芜雪野湖介绍,企业定制app,罗田住房和城乡建设局网站一、VFS 虚拟文件系统基础概念 Linux 允许众多不同的文件系统共存#xff0c;并支持跨文件系统的文件操作#xff0c;这是因为有虚拟文件系统的存在。虚拟文件系统#xff0c;即VFS#xff08;Virtual File System#xff09;是 Linux 内核中的一个软件抽象层。它通过一些… 一、VFS 虚拟文件系统基础概念 Linux 允许众多不同的文件系统共存并支持跨文件系统的文件操作这是因为有虚拟文件系统的存在。虚拟文件系统即VFSVirtual File System是 Linux 内核中的一个软件抽象层。它通过一些数据结构及其方法向实际的文件系统如 ext2vfat 提供接口机制。 Linux 有两个特性 a --  跨文件系统的文件操作 Linux 中允许众多不同的文件系统共存如 ext2, ext3, vfat 等。通过使用同一套文件 I/O 系统调用即可对 Linux 中的任意文件进行操作而无需考虑其所在的具体文件系统格式更进一步对文件的操作可以跨文件系统而执行。如图 1 所示我们可以使用 cp 命令从 vfat 文件系统格式的硬盘拷贝数据到 ext3 文件系统格式的硬盘而这样的操作涉及到两个不同的文件系统。 图 1. 跨文件系统的文件操作 b -- 一切皆是文件 “一切皆是文件”是 Unix/Linux 的基本哲学之一。不仅普通的文件目录、字符设备、块设备、套接字等在 Unix/Linux 中都是以文件被对待它们虽然类型不同但是对其提供的却是同一套操作界面。 图 2. 一切皆是文件 而虚拟文件系统正是实现上述两点 Linux 特性的关键所在。虚拟文件系统Virtual File System, 简称 VFS是 Linux 内核中的一个软件层用于给用户空间的程序提供文件系统接口同时它也提供了内核中的一个抽象功能允许不同的文件系统共存。系统中所有的文件系统不但依赖 VFS 共存而且也依靠 VFS 协同工作。 为了能够支持各种实际文件系统VFS 定义了所有文件系统都支持的基本的、概念上的接口和数据结构同时实际文件系统也提供 VFS 所期望的抽象接口和数据结构将自身的诸如文件、目录等概念在形式上与VFS的定义保持一致。换句话说一个实际的文件系统想要被 Linux 支持就必须提供一个符合VFS标准的接口才能与 VFS 协同工作。就像《老炮儿》里面的一样“要有规矩”想在Linux下混就要按照Linux所定的规矩来办事。实际文件系统在统一的接口和数据结构下隐藏了具体的实现细节所以在VFS 层和内核的其他部分看来所有文件系统都是相同的。 图3显示了VFS在内核中与实际的文件系统的协同关系。 图3. VFS在内核中与其他的内核模块的协同关系 总结虚拟文件系统的作用 虚拟文件系统(VFS)是linux内核和存储设备之间的抽象层主要有以下好处。 - 简化了应用程序的开发应用通过统一的系统调用访问各种存储介质 - 简化了新文件系统加入内核的过程新文件系统只要实现VFS的各个接口即可不需要修改内核部分 二、 VFS数据结构 1 、一些基本概念 从本质上讲文件系统是特殊的数据分层存储结构它包含文件、目录和相关的控制信息。 为了描述这个结构Linux引入了一些基本概念: 文件  一组在逻辑上具有完整意义的信息项的系列。在Linux中除了普通文件其他诸如目录、设备、套接字等也以文件被对待。总之“一切皆文件”。 目录  目录好比一个文件夹用来容纳相关文件。因为目录可以包含子目录所以目录是可以层层嵌套形成文件路径。在Linux中目录也是以一种特殊文件被对待的所以用于文件的操作同样也可以用在目录上。 目录项 在一个文件路径中路径中的每一部分都被称为目录项如路径/home/source/helloworld.c中目录 /, home, source和文件 helloworld.c都是一个目录项。 索引节点 用于存储文件的元数据的一个数据结构。文件的元数据也就是文件的相关信息和文件本身是两个不同的概念。它包含的是诸如文件的大小、拥有者、创建时间、磁盘位置等和文件相关的信息。 超级块 用于存储文件系统的控制信息的数据结构。描述文件系统的状态、文件系统类型、大小、区块数、索引节点数等存放于磁盘的特定扇区中。 如上的几个概念在磁盘中的位置关系如图4所示。 图4. 磁盘与文件系统 2、VFS数据结构 VFS依靠四个主要的数据结构和一些辅助的数据结构来描述其结构信息这些数据结构表现得就像是对象每个主要对象中都包含由操作函数表构成的操作对象这些操作对象描述了内核针对这几个主要的对象可以进行的操作。 a -- 超级块对象 存储一个已安装的文件系统的控制信息代表一个已安装的文件系统每次一个实际的文件系统被安装时内核会从磁盘的特定位置读取一些控制信息来填充内存中的超级块对象。一个安装实例和一个超级块对象一一对应。超级块通过其结构中的一个域s_type记录它所属的文件系统类型。 超级块的定义在linux/fs.h [cpp] view plaincopy /*    * 超级块结构中定义的字段非常多   * 这里只介绍一些重要的属性   */   struct super_block {       struct list_head    s_list;               /* 指向所有超级块的链表 */       const struct super_operations    *s_op; /* 超级块方法 */       struct dentry        *s_root;           /* 目录挂载点 */       struct mutex        s_lock;            /* 超级块信号量 */       int            s_count;                   /* 超级块引用计数 */          struct list_head    s_inodes;           /* inode链表 */       struct mtd_info        *s_mtd;            /* 存储磁盘信息 */       fmode_t            s_mode;                /* 安装权限 */   };      /*   * 其中的 s_op 中定义了超级块的操作方法   * 这里只介绍一些相对重要的函数   */   struct super_operations {          struct inode *(*alloc_inode)(struct super_block *sb); /* 创建和初始化一个索引节点对象 */       void (*destroy_inode)(struct inode *);                /* 释放给定的索引节点 */             void (*dirty_inode) (struct inode *);                 /* VFS在索引节点被修改时会调用这个函数 */       int (*write_inode) (struct inode *, int);             /* 将索引节点写入磁盘wait表示写操作是否需要同步 */       void (*drop_inode) (struct inode *);                  /* 最后一个指向索引节点的引用被删除后VFS会调用这个函数 */       void (*delete_inode) (struct inode *);                /* 从磁盘上删除指定的索引节点 */       void (*put_super) (struct super_block *);             /* 卸载文件系统时由VFS调用用来释放超级块 */       void (*write_super) (struct super_block *);           /* 用给定的超级块更新磁盘上的超级块 */       int (*sync_fs)(struct super_block *sb, int wait);     /* 使文件系统中的数据与磁盘上的数据同步 */       int (*statfs) (struct dentry *, struct kstatfs *);    /* VFS调用该函数获取文件系统状态 */       int (*remount_fs) (struct super_block *, int *, char *); /* 指定新的安装选项重新安装文件系统时VFS会调用该函数 */       void (*clear_inode) (struct inode *);                 /* VFS调用该函数释放索引节点并清空包含相关数据的所有页面 */       void (*umount_begin) (struct super_block *);          /* VFS调用该函数中断安装操作 */   };   b -- 索引节点对象索引节点对象存储了文件的相关信息代表了存储设备上的一个实际的物理文件。当一个文件首次被访问时内核会在内存中组装相应的索引节点对象以便向内核提供对一个文件进行操作时所必需的全部信息这些信息一部分存储在磁盘特定位置另外一部分是在加载时动态填充的。 索引节点定义在linux/fs.h [cpp] view plaincopy /*    * 索引节点结构中定义的字段非常多   * 这里只介绍一些重要的属性   */   struct inode {       struct hlist_node    i_hash;     /* 散列表用于快速查找inode */       struct list_head    i_list;        /* 索引节点链表 */       struct list_head    i_sb_list;  /* 超级块链表超级块  */       struct list_head    i_dentry;   /* 目录项链表 */       unsigned long        i_ino;      /* 节点号 */       atomic_t        i_count;        /* 引用计数 */       unsigned int        i_nlink;    /* 硬链接数 */       uid_t            i_uid;          /* 使用者id */       gid_t            i_gid;          /* 使用组id */       struct timespec        i_atime;    /* 最后访问时间 */       struct timespec        i_mtime;    /* 最后修改时间 */       struct timespec        i_ctime;    /* 最后改变时间 */       const struct inode_operations    *i_op;  /* 索引节点操作函数 */       const struct file_operations    *i_fop;    /* 缺省的索引节点操作 */       struct super_block    *i_sb;              /* 相关的超级块 */       struct address_space    *i_mapping;     /* 相关的地址映射 */       struct address_space    i_data;         /* 设备地址映射 */       unsigned int        i_flags;            /* 文件系统标志 */       void            *i_private;             /* fs 私有指针 */   };      /*   * 其中的 i_op 中定义了索引节点的操作方法   * 这里只介绍一些相对重要的函数   */   struct inode_operations {       /* 为dentry对象创造一个新的索引节点 */       int (*create) (struct inode *,struct dentry *,int, struct nameidata *);       /* 在特定文件夹中寻找索引节点该索引节点要对应于dentry中给出的文件名 */       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);       /* 创建硬链接 */       int (*link) (struct dentry *,struct inode *,struct dentry *);       /* 从一个符号链接查找它指向的索引节点 */       void * (*follow_link) (struct dentry *, struct nameidata *);       /* 在 follow_link调用之后该函数由VFS调用进行清除工作 */       void (*put_link) (struct dentry *, struct nameidata *, void *);       /* 该函数由VFS调用用于修改文件的大小 */       void (*truncate) (struct inode *);   };   c -- 目录项和超级块和索引节点不同目录项并不是实际存在于磁盘上的。在使用的时候在内存中创建目录项对象其实通过索引节点已经可以定位到指定的文件但是索引节点对象的属性非常多在查找比较文件时直接用索引节点效率不高所以引入了目录项的概念。这里可以看做又引入了一个抽象层目录项是对索引节点的抽象路径中的每个部分都是一个目录项比如路径 /mnt/cdrom/foo/bar 其中包含5个目录项/ mnt cdrom foo bar 每个目录项对象都有3种状态被使用未使用和负状态 - 被使用对应一个有效的索引节点并且该对象由一个或多个使用者 - 未使用对应一个有效的索引节点但是VFS当前并没有使用这个目录项 - 负状态没有对应的有效索引节点可能索引节点被删除或者路径不存在了 目录项定义在linux/dcache.h [cpp] view plaincopy /* 目录项对象结构 */   struct dentry {       atomic_t d_count;       /* 使用计数 */       unsigned int d_flags;   /* 目录项标识 */       spinlock_t d_lock;        /* 单目录项锁 */       int d_mounted;          /* 是否登录点的目录项 */       struct inode *d_inode;    /* 相关联的索引节点 */       struct hlist_node d_hash;    /* 散列表 */       struct dentry *d_parent;    /* 父目录的目录项对象 */       struct qstr d_name;         /* 目录项名称 */       struct list_head d_lru;        /* 未使用的链表 */       /*       * d_child and d_rcu can share memory       */       union {           struct list_head d_child;    /* child of parent list */            struct rcu_head d_rcu;       } d_u;       struct list_head d_subdirs;    /* 子目录链表 */       struct list_head d_alias;    /* 索引节点别名链表 */       unsigned long d_time;        /* 重置时间 */       const struct dentry_operations *d_op; /* 目录项操作相关函数 */       struct super_block *d_sb;    /* 文件的超级块 */       void *d_fsdata;            /* 文件系统特有数据 */          unsigned char d_iname[DNAME_INLINE_LEN_MIN];    /* 短文件名 */   };      /* 目录项相关操作函数 */   struct dentry_operations {       /* 该函数判断目录项对象是否有效。VFS准备从dcache中使用一个目录项时会调用这个函数 */       int (*d_revalidate)(struct dentry *, struct nameidata *);       /* 为目录项对象生成hash值 */       int (*d_hash) (struct dentry *, struct qstr *);       /* 比较 qstr 类型的2个文件名 */       int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);       /* 当目录项对象的 d_count 为0时VFS调用这个函数 */       int (*d_delete)(struct dentry *);       /* 当目录项对象将要被释放时VFS调用该函数 */       void (*d_release)(struct dentry *);       /* 当目录项对象丢失其索引节点时也就是磁盘索引节点被删除了VFS会调用该函数 */       void (*d_iput)(struct dentry *, struct inode *);       char *(*d_dname)(struct dentry *, char *, int);   };   d -- 文件对象文件对象是已打开的文件在内存中的表示主要用于建立进程和磁盘上的文件的对应关系。 即文件对象并不是一个文件只是抽象的表示一个打开的文件对。文件对象和物理文件的关系有点像进程和程序的关系一样。 它由sys_open() 现场创建由sys_close()销毁。当我们站在用户空间来看待VFS我们像是只需与文件对象打交道而无须关心超级块索引节点或目录项。因为多个进程可以同时打开和操作同一个文件所以同一个文件也可能存在多个对应的文件对象。文件对象仅仅在进程观点上代表已经打开的文件它反过来指向目录项对象反过来指向索引节点。 一个文件对应的文件对象可能不是惟一的但是其对应的索引节点和目录项对象无疑是惟一的。 文件对象的定义在: linux/fs.h [cpp] view plaincopy /*    * 文件对象结构中定义的字段非常多   * 这里只介绍一些重要的属性   */   struct file {       union {           struct list_head    fu_list;    /* 文件对象链表 */           struct rcu_head     fu_rcuhead; /* 释放之后的RCU链表 */       } f_u;       struct path        f_path;             /* 包含的目录项 */       const struct file_operations    *f_op; /* 文件操作函数 */       atomic_long_t        f_count;        /* 文件对象引用计数 */   };      /*   * 其中的 f_op 中定义了文件对象的操作方法   * 这里只介绍一些相对重要的函数   */   struct file_operations {       /* 用于更新偏移量指针,由系统调用lleek()调用它 */       loff_t (*llseek) (struct file *, loff_t, int);       /* 由系统调用read()调用它 */       ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);       /* 由系统调用write()调用它 */       ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);       /* 由系统调用 aio_read() 调用它 */       ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);       /* 由系统调用 aio_write() 调用它 */       ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);       /* 将给定文件映射到指定的地址空间上,由系统调用 mmap 调用它 */       int (*mmap) (struct file *, struct vm_area_struct *);       /* 创建一个新的文件对象,并将它和相应的索引节点对象关联起来 */       int (*open) (struct inode *, struct file *);       /* 当已打开文件的引用计数减少时,VFS调用该函数 */       int (*flush) (struct file *, fl_owner_t id);   };   上面分别介绍了4种对象分别的属性和方法,下面用图来展示这4个对象的和VFS之间关系以及4个对象之间的关系。 VFS中4个主要对象 前面我们讲到超级块和索引节点都是真实存在的是一个实际的物理文件。即使基于内存的文件系统也是一种抽象的实际物理文件而目录项对象和文件对象是运行时才被创建的。 下面是VFS中4个主要对象之间的关系 超级块是一个文件系统一个文件系统中可以有多个索引节点索引节点和目录的关系又是 NM一个目录中可以有多个文件对象但一个文件对象却只能有一个目录; 三、基于VFS的文件I/O 到目前为止文章主要都是从理论上来讲述VFS的运行机制接下来我们将深入源代码层中通过阐述两个具有代表性的系统调用sys_open()和sys_read()来更好地理解VFS 向具体文件系统提供的接口机制。由于本文更关注的是文件操作的整个流程体制所以我们在追踪源代码时对一些细节性的处理不予关心。又由于篇幅所限只列出相关代码。本文中的源代码来自于linux-2.6.17内核版本。 在深入sys_open()和sys_read()之前我们先概览下调用sys_read()的上下文。下图描述了从用户空间的read()调用到数据从磁盘读出的整个流程。 当在用户应用程序调用文件I/O read()操作时系统调用sys_read()被激发sys_read()找到文件所在的具体文件系统把控制权传给该文件系统最后由具体文件系统与物理介质交互从介质中读出数据。 1、sys_open() sys_open()系统调用打开或创建一个文件成功返回该文件的文件描述符。图8是sys_open()实现代码中主要的函数调用关系图。 图8. sys_open函数调用关系图 由于sys_open()的代码量大函数调用关系复杂以下主要是对该函数做整体的解析而对其中的一些关键点则列出其关键代码。 a -- 从sys_open()的函数调用关系图可以看到sys_open()在做了一些简单的参数检验后就把接力棒传给do_sys_open() 1、首先get_unused_fd()得到一个可用的文件描述符通过该函数可知文件描述符实质是进程打开文件列表中对应某个文件对象的索引值 2、接着do_filp_open()打开文件返回一个file对象代表由该进程打开的一个文件进程通过这样的一个数据结构对物理文件进行读写操作。 3、最后fd_install()建立文件描述符与file对象的联系以后进程对文件的读写都是通过操纵该文件描述符而进行。 b -- do_filp_open()用于打开文件返回一个file对象而打开之前需要先找到该文件 1、open_namei()用于根据文件路径名查找文件借助一个持有路径信息的数据结构nameidata而进行 2、查找结束后将填充有路径信息的nameidata返回给接下来的函数nameidata_to_filp()从而得到最终的file对象当达到目的后nameidata这个数据结构将会马上被释放。 c -- open_namei()用于查找一个文件 1、path_lookup_open()实现文件的查找功能要打开的文件若不存在还需要有一个新建的过程则调用path_lookup_create()后者和前者封装的是同一个实际的路径查找函数只是参数不一样使它们在处理细节上有所偏差 2、当是以新建文件的方式打开文件时即设置了O_CREAT标识时需要创建一个新的索引节点代表创建一个文件。在vfs_create()里的一句核心语句dir-i_op-create(dir, dentry, mode, nd)可知它调用了具体的文件系统所提供的创建索引节点的方法。注意这边的索引节点的概念还只是位于内存之中它和磁盘上的物理的索引节点的关系就像位于内存中和位于磁盘中的文件一样。此时新建的索引节点还不能完全标志一个物理文件的成功创建只有当把索引节点回写到磁盘上才是一个物理文件的真正创建。想想我们以新建的方式打开一个文件对其读写但最终没有保存而关闭则位于内存中的索引节点会经历从新建到消失的过程而磁盘却始终不知道有人曾经想过创建一个文件这是因为索引节点没有回写的缘故。 3、path_to_nameidata()填充nameidata数据结构 4、may_open()检查是否可以打开该文件一些文件如链接文件和只有写权限的目录是不能被打开的先检查nd-dentry-inode所指的文件是否是这一类文件是的话则错误返回。还有一些文件是不能以TRUNC的方式打开的若nd-dentry-inode所指的文件属于这一类则显式地关闭TRUNC标志位。接着如果有以TRUNC方式打开文件的则更新nd-dentry-inode的信息 d -- __path_lookup_intent_open() 不管是path_lookup_open()还是path_lookup_create()最终都是调用__path_lookup_intent_open()来实现查找文件的功能。查找时在遍历路径的过程中会逐层地将各个路径组成部分解析成目录项对象如果此目录项对象在目录项缓存中则直接从缓存中获得如果该目录项在缓存中不存在则进行一次实际的读盘操作从磁盘中读取该目录项所对应的索引节点。得到索引节点后则建立索引节点与该目录项的联系。如此循环直到最终找到目标文件对应的目录项也就找到了索引节点而由索引节点找到对应的超级块对象就可知道该文件所在的文件系统的类型。从磁盘中读取该目录项所对应的索引节点这将引发VFS和实际的文件系统的一次交互。从前面的VFS理论介绍可知读索引节点方法是由超级块来提供的。而当安装一个实际的文件系统时在内存中创建的超级块的信息是由一个实际文件系统的相关信息来填充的这里的相关信息就包括了实际文件系统所定义的超级块的操作函数列表当然也就包括了读索引节点的具体执行方式。当继续追踪一个实际文件系统ext3的ext3_read_inode()时可发现这个函数很重要的一个工作就是为不同的文件类型设置不同的索引节点操作函数表和文件操作函数表。 清单8. ext3_read_inode [cpp] view plaincopy void ext3_read_inode(struct inode * inode)      {         ……         //是普通文件                  if (S_ISREG(inode-i_mode)) {            inode-i_op  ext3_file_inode_operations;            inode-i_fop  ext3_file_operations;            ext3_set_aops(inode);         } else if (S_ISDIR(inode-i_mode)) {            //是目录文件            inode-i_op  ext3_dir_inode_operations;            inode-i_fop  ext3_dir_operations;         } else if (S_ISLNK(inode-i_mode)) {            // 是连接文件             ……         } else {             // 如果以上三种情况都排除了则是设备驱动            //这里的设备还包括套结字、FIFO等伪设备             ……    e -- nameidata_to_filp子函数__dentry_open 这是VFS与实际的文件系统联系的一个关键点。从3.1.1小节分析中可知调用实际文件系统读取索引节点的方法读取索引节点时实际文件系统会根据文件的不同类型赋予索引节点不同的文件操作函数集如普通文件有普通文件对应的一套操作函数设备文件有设备文件对应的一套操作函数。这样当把对应的索引节点的文件操作函数集赋予文件对象以后对该文件进行操作时比如读操作VFS虽然对各种不同文件都是执行同一个read()操作界面但是真正读时内核却知道怎么区分对待不同的文件类型。 清单9. __dentry_open [cpp] view plaincopy  static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,                       int flags, struct file *f,                       int (*open)(struct inode *, struct file *))       {           struct inode *inode;           ……           //整个函数的工作在于填充一个file对象           ……            f-f_mapping  inode-i_mapping;             f-f_dentry  dentry;           f-f_vfsmnt  mnt;           f-f_pos  0;             //将对应的索引节点的文件操作函数集赋予文件对象的操作列表           f-f_op  fops_get(inode-i_fop);            ……             //若文件自己定义了open操作则执行这个特定的open操作。           if (!open  f-f_op)              open  f-f_op-open;            if (open) {              error  open(inode, f);              if (error)                 goto cleanup_all;           ……           return f;   }   2、 sys_read() sys_read()系统调用用于从已打开的文件读取数据。如read成功则返回读到的字节数。如已到达文件的尾端则返回0。图9是sys_read()实现代码中的函数调用关系图。 对文件进行读操作时需要先打开它。从3.1小结可知打开一个文件时会在内存组装一个文件对象希望对该文件执行的操作方法已在文件对象设置好。所以对文件进行读操作时VFS在做了一些简单的转换后由文件描述符得到其对应的文件对象其核心思想是返回current-files-fd[fd]所指向的文件对象就可以通过语句file-f_op-read(file, buf, count, pos)轻松调用实际文件系统的相应方法对文件进行读操作了。 四、解决问题 1、 跨文件系统的文件操作的基本原理 到此我们也就能够解释在Linux中为什么能够跨文件系统地操作文件了。举个例子将vfat格式的磁盘上的一个文件a.txt拷贝到ext3格式的磁盘上命名为b.txt。这包含两个过程对a.txt进行读操作对b.txt进行写操作。读写操作前需要先打开文件。由前面的分析可知打开文件时VFS会知道该文件对应的文件系统格式以后操作该文件时VFS会调用其对应的实际文件系统的操作方法。 所以VFS调用vfat的读文件方法将a.txt的数据读入内存在将a.txt在内存中的数据映射到b.txt对应的内存空间后VFS调用ext3的写文件方法将b.txt写入磁盘从而实现了最终的跨文件系统的复制操作。 2、“一切皆是文件”的实现根本 不论是普通的文件还是特殊的目录、设备等VFS都将它们同等看待成文件通过同一套文件操作界面来对它们进行操作。操作文件时需先打开打开文件时VFS会知道该文件对应的文件系统格式当VFS把控制权传给实际的文件系统时实际的文件系统再做出具体区分对不同的文件类型执行不同的操作。这也就是“一切皆是文件”的根本所在。 五、总结 VFS即虚拟文件系统是Linux文件系统中的一个抽象软件层因为它的支持众多不同的实际文件系统才能在Linux中共存跨文件系统操作才能实现。 VFS借助它四个主要的数据结构即超级块、索引节点、目录项和文件对象以及一些辅助的数据结构向Linux中不管是普通的文件还是目录、设备、套接字等都提供同样的操作界面如打开、读写、关闭等。只有当把控制权传给实际的文件系统时实际的文件系统才会做出区分对不同的文件类型执行不同的操作。由此可见正是有了VFS的存在跨文件系统操作才能执行Unix/Linux中的“一切皆是文件”的口号才能够得以实现。
http://www.yutouwan.com/news/57684/

相关文章:

  • 都是做面食网站建设工程合同在性质上属于什么合同
  • 养生网站建设河南郑州建设网站制作
  • 专业网站设计公司排名外贸服装商城网站建设
  • 关于网站建设管理工作的报告修改散文网站
  • 如何做同城信息网站wordpress post编辑
  • 网站服务器上线后要怎么做软件开发app开发定制外包99
  • 网站建设 洪塔福田网站制作比较好的
  • 贵州省网站建设选哪家安徽建站优化哪里有
  • 怎么做能打不开漫画网站安庆市建设局网站首页
  • 郓城网站建设电话临沂消防建设局官方网站
  • 25转行做网站运营重庆平台网站建设哪家有
  • 做免费漫画网站有风险吗wordpress文章背景
  • 做网站赚钱多吗设计在线官网作品欣赏
  • django mysql网站开发求推荐建设网站
  • 建设电商网站报价提供网站建设方案服务
  • 哪些网站做国际贸易比较好redis wordpress缓存
  • 网站百度搜索不到新桥网站建设培训
  • 找网站做任务领q币wordpress文章发布器
  • 网站正在开发中国内html网站欣赏
  • 国内四大门户网站山东省建筑工程信息网
  • 网站开发的职业规划金华永康网站建设
  • 微动网站建设桂林象鼻山作文400字
  • wordpress建站更新带动器
  • 什么软件可以发布做网站如何注册一家公司要多少钱
  • wordpress换域名中山网站搜索优化
  • 公司网站建设方案详细方案模板安卓小程序制作
  • 深圳罗湖医疗集团网站建设wordpress图片分页插件下载
  • 中国做外贸最好的网站有哪些wordpress iis 中文乱码
  • dede搭建网站教程平顶山专业做网站公司
  • 佛山网站建设zingup中投建设官方网站