《Linux内核设计与实现》笔记——VFS

关于VFS有一篇很好的博客http://www.ibm.com/developerworks/cn/linux/l-vfs/

建议先阅读本文为基础,然后继续阅读该文章。

VFS,虚拟文件系统,为用户提供了文件和文件系统相关的接口。

这些接口可以跨越各种文件系统和不同介质执行。

VFS提供了一个通用文件系统模型,该模型囊括了任何文件系统的常用功能集和行为。

该模型偏重于Unix风格的文件系统。

数据结构关系

如下图,下图描述了VFS相关数据结构的关系

Unix文件系统

Unix使用了4个和文件系统相关的传统概念:文件目录项索引节点安装点(mount point)

文件

简单的面向字节流的抽象

目录项

文件通过目录组织起来,目录中的每一个部分都是一个目录条目, /home/wolfman/butter , / , home, wolfman , butter 都是目录条目,统称为目录项

索引节点

Unix文件系统,将文件的相关信息和文件本身区分开来。文件控制信息,如权限,拥有者,大小,创建时间等”元数据”,被存储在一个单独的数据结构中,该结构被称为索引节点inode

安装点/挂载点

linux中的磁盘文件系统的入口目录,类似于windows中的用来访问不同分区的C:、D:、E:等盘符。[百度百科词条]

文件系统的信息存储在超级块中,集单独文件信息和文件系统信息于一身。

对于FAT,NTFS这种,虽然也可以在Linux上工作,但必须进行封装。比如:一个文件系统不支持索引节点,也必须在内存中装配索引节点结构体,就像它本身包含一样。

VFS对象及数据结构

  • 超级块对象

    • 代表一个具体的已安装文件系统,由super_block结构体表示,定义于<linux/fs.h>
    • 包含操作对象super_operations对象,包括内核针对特定文件系统所能调用的方法,定义于<linux/fs.h>
      • 超级块对象通过alloc_super()函数创建并初始化。在文件系统安装时,文件系统会调用该函数以便从磁盘读取文件系统超级块,并将其信息填充到内存中的超级块对象中
    • 各种文件系统都必须实现超级块对象,该对象用于存储特定文件系统信息,通常对应于存放在磁盘特定扇区的文件系统超级块或系统控制块。

      super_block

      http://lxr.free-electrons.com/source/include/linux/fs.h?v=3.11#L1242

      super_operations

      http://lxr.free-electrons.com/source/include/linux/fs.h?v=3.11#L1604

  • 索引节点对象
    • 代表一个具体文件,包含了内核在操作文件或目录时需要的全部信息,由inode结构体表示,定义于<linux/fs.h>

      • unix风格的文件系统可以直接从磁盘索引节点读入,如果一个文件系统没有索引节点,文件系统需要从磁盘上提取相关信息(没有inode的文件系统通常将文件描述信息作为文件的一部分)
      • 索引节点必须在内存中创建,以便于文件系统使用
    • 包含操作对象inode_operations对象,包括针对特定文件所能调用的方法,定义于<linux/fs.h>
    • 索引节点代表文件系统中的一个文件(但索引节点仅当文件被访问时,才在内存中创建),也可以是设备管道这样的特殊文件

      inode

      http://lxr.free-electrons.com/source/include/linux/fs.h?v=3.11#L523

      inode_operations

      http://lxr.free-electrons.com/source/include/linux/fs.h?v=3.11#L1559

  • 目录项对象
    • 代表一个目录项,是路径的一个组成部分,由dentry结构体表示,定义于<linux/dcache.h>
    • 包含dentry_operations对象,其中包括内核针对特定目录所能调用的方法,定义<linux/dcache.h>
    • VFS把目录当文件对待,路径中的每一个组成部分都由一个索引节点对象表示。为方便查找操作,vfs引入目录项,每个dentry代表路径中的一个特定部分,/bin/vi,这个路径,/,bin,vi(文件)都是目录项对象。
    • 目录项也可包括安装点,/mnt/cdrom/foo,构成元素/,mnt,cdrom,foo都是目录项
    • vfs在执行目录操作时,如果需要会现场创建目录项对象。
    • 目录学没有对应的磁盘数据结构,vfs根据字符串路径名现场创建
    • 目录项缓存在目录项缓存dcache中,以加速查找操作

      dentry

      http://lxr.free-electrons.com/source/include/linux/dcache.h?v=3.11#L106

      dentry_operations

      http://lxr.free-electrons.com/source/include/linux/dcache.h?v=3.11#L148

  • 文件对象
    • 代表由进程打开的文件,由file结构体表示,定义于<linux/fs.h>
    • 包含file_operations对象,其中包括进程针对已经打开的文件所能调用的方法,定义于<linux/fs.h>
    • 多个进程可以同时打开和操作同一个文件,所以同一个文件可能对应多个文件对象。
    • 文件对象仅在进程观点上代表已打开文件,它反过来指向dentry(反过来指向inode),只有目录项才代表打开的实际文件。文件对应的文件对象不是唯一的,但对应的索引节点和目录项对象和文件是唯一的。

      file

      http://lxr.free-electrons.com/source/include/linux/fs.h?v=3.11#L765

      file_operations

      http://lxr.free-electrons.com/source/include/linux/fs.h?v=3.11#L1528

      因为VFS将目录作为一个文件来处理,所以不存在目录对象。

其他相关数据结构

和文件系统相关的数据结构

  • file_system_type

    • 用来描述各种特定文件系统,定义于<linux/fs.h>,如ext3,ext4
    • 每种文件系统,不论是否被安装,都只有一个file_system_type结构体

      kernel 3.11

struct file_system_type {
         const char *name;
         int fs_flags;
#define FS_REQUIRES_DEV         1
#define FS_BINARY_MOUNTDATA     2
#define FS_HAS_SUBTYPE          4
#define FS_USERNS_MOUNT         8       //Can be mounted by userns root
#define FS_USERNS_DEV_MOUNT     16 // A userns mount does not imply MNT_NODEV
#define FS_RENAME_DOES_D_MOVE   32768   /* FS will handle d_move() during rename() internally. */
         struct dentry *(*mount) (struct file_system_type *, int,const char *, void *);
        void (*kill_sb) (struct super_block *);
        struct module *owner;
        struct file_system_type * next;
        struct hlist_head fs_supers;

        struct lock_class_key s_lock_key;
        struct lock_class_key s_umount_key;
        struct lock_class_key s_vfs_rename_key;
        struct lock_class_key s_writers_key[SB_FREEZE_LEVELS];

        struct lock_class_key i_lock_key;
        struct lock_class_key i_mutex_key;
        struct lock_class_key i_mutex_dir_key;
};
  • vfsmont

    • 用来描述一个安装文件系统的实例,定义于<linux/mount.h>
    • 文件系统被实际安装时,一个vfsmount结构在安装点创建,代表文件系统的实例,换句话说,代表安装点。
struct vfsmount {
     struct dentry *mnt_root;/* root of the mounted tree */
     struct super_block *mnt_sb;/* pointer to superblock */
     int mnt_flags;
};

和进程相关的数据结构

file_struct

定义于<linux/fdtable.h> 与单个进程相关的信息都包含在内

fs_struct

定义于<linux/fs_struct.h> 包含文件系统和进程相关信息

namespace

定义于<linux/mnt_namespace.h>

使得每一个进程在系统中看到唯一的安装文件系统,不仅是唯一的根目录,而是唯一的文件系统层次结构

Linux存储栈

[ https://www.thomaskrenn.com/en/wiki/Linux_Storage_Stack_Diagram ]

时间: 2024-08-29 07:31:27

《Linux内核设计与实现》笔记——VFS的相关文章

《Linux内核设计与实现》读书笔记——第一二章

<Linux内核设计与实现>读书笔记——第一二章 第一章 Linux内核简介 1.1 Unix的历史 简洁:仅提供系统调用并有一个非常明确的设计目的. 抽象:Unix中绝大部分东西都被当做文件,这种抽象使对数据和对设备的操作是通过一套相同的系统调用接口来进行的(open().read().write().lseek().close()). 可移植:使用C语言编写,使其在各种硬件体系架构面前都具备令人惊异的移植能力. 进程创建迅速:有独特的fork()系统调用,一次执行保质保量地完成一个任务.简

【读书笔记】《Linux内核设计与实现》内核同步介绍&内核同步方法

简要做个笔记,以备忘. 需同步的原因是,我们并发访问了共享资源.我们将访问或操作共享资源的代码段称"临界区",如果两个执行线程处于同一临界区中同时执行,称"竞争条件".这里术语执行线程指任何正在执行的代码实例,如一个在内核执行的进程.一个中断处理程序或一个内核线程. 举个简单例子,i++操作.该操作可以转换为下面的机器指令序列: 1.得到当前变量i的值,并保存到一个寄存器. 2.将寄存器的值加1. 3.将i的新值写回到内存中. 当两个线程同时进入这个临界区,若i初值

《Linux内核设计与实现》笔记-1-linux内核简介

一.Linux内核相对于传统的UNIX内核的比较: (1):Linux支持动态内核模块.尽管Linux内核也是整体式结构,可是允许在需要的时候动态哦卸除(rmmod xxx)和加载内核模块(insmod  xxx.ko). (2):Linux支持对称多处理(SMP)机制,尽管许多UNIX的变体也支持SMP,但是传统的UNIX并不支持这种机制. (3):Linux内核可以抢占(preemptive).在Linux 2.4以及以前的版本都是不支持内核抢占的,在Linux 2.6以及以后就支持了. (

《Linux内核设计与实现》Chapter 2 读书笔记

<Linux内核设计与实现>Chapter 2 读书笔记 一.获取内核源码 1.使用Git 我们曾经在以前的学习中使用过Git方法 $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git 更新分支到Linux的最新分支 $ git pull 可以获取并随时保持与内核官方的代码树一致 2.安装内核源代码 压缩形式为bzip2 $ tar xvjf linux-x.y.z.tar.bz2 压缩

《LINUX内核设计的艺术》第一章从开机家电到执行main函数之前的过程 学习笔记之一

从开机加电到实行main函数之前的过程 分为三步,目的是实现从启动盘加载操作系统程序,完成实现main函数的准备工作 启动BLOS,准备是模式下的中断向量表和中断服务程序 从启动盘加载操作系统程序到内存.加载操作系统程序就是靠第一步实现的 为实现32位的main函数做过度工作 1.1启动blos,准备实模式下的中断向量表和中断服务程序 由blos来加载软件操作系统的任务 1.1.1         BLOS的启动原理 0XFFFF0 由硬件来启动,CPU硬件设计逻辑设计为加电瞬间就强行将CS的值

《Linux内核设计与实现》 Chapter4 读书笔记

<Linux内核设计与实现> Chapter4 读书笔记 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统. 一.多任务 多任务操作系统就是能同时并发地交互执行多个进程的操作系统. 多任务系统可以划分为两类: 非抢占式多任务 进程会一直执行直到自己主动停止运行 抢占式多任务 Linux/Unix使用的是抢占式的方式:强制的挂起进程的动作就叫做抢占. 像所有unix的变体和许多其他现代操作系统一样,Linux提

《Linux内核设计与实现》第一、二章学习笔记

<Linux内核设计与实现>第一.二章学习笔记 姓名:王玮怡  学号:20135116 第一章 Linux内核简介 一.关于Unix ——一个支持抢占式多任务.多线程.虚拟内存.换页.动态链接和TCP/IP网络的现代化操作系统 1.主要发展过程   1969年,贝尔实验室的程序员们设计了一个文件系统原型,最终发展演化成了Unix 1971年,Unix被移植到PDP-11型机中 1973年,整个Unix系统使用C语言进行重写,为后来Unix系统的广泛移植铺平了道路 Unix第六版(V6)被贝尔实

Linux内核设计与实现 读书笔记 转

Linux内核设计与实现  读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://blog.csdn.net/yrj/article/category/718110 Linux内存管理和性能学习笔记(一) :内存测量与堆内存 第一篇 内存的测量 2.1. 系统当前可用内存 # cat /proc/meminfoMemTotal:        8063544 kBMemFree:       

《Linux内核设计与实现》读书笔记(十一)- 定时器和时间管理

系统中有很多与时间相关的程序(比如定期执行的任务,某一时间执行的任务,推迟一段时间执行的任务),因此,时间的管理对于linux来说非常重要. 主要内容: 系统时间 定时器 定时器相关概念 定时器执行流程 实现程序延迟的方法 定时器和延迟的例子 1. 系统时间 系统中管理的时间有2种:实际时间和定时器. 1.1  实际时间 实际时间就是现实中钟表上显示的时间,其实内核中并不常用这个时间,主要是用户空间的程序有时需要获取当前时间, 所以内核中也管理着这个时间. 实际时间的获取是在开机后,内核初始化时

《Linux内核设计与实现》Chapter 5 读书笔记

<Linux内核设计与实现>Chapter 5 读书笔记 在现代操作系统中,内核提供了用户进程与内核进行交互的一组接口,这些接口的作用是: 使应用程序受限地访问硬件设备 提供创建新进程与已有进程进行通信的机制 提供申请操作系统其他资源的能力 一.与内核通信 1.系统调用的作用 系统调用在用户空间进程和硬件设备之间添加了一个中间层,作用是: 为用户空间提供了一种硬件抽象接口: 系统调用保证了系统的稳定和安全,即可以避免应用程序不正确地使用硬件设备,窃取其他进程的资源: 每个进程都运行在虚拟系统中