ホームページ >システムチュートリアル >Linux >Linux仮想ファイルシステムの原理を詳しく説明する

Linux仮想ファイルシステムの原理を詳しく説明する

WBOY
WBOY転載
2024-02-15 09:21:11534ブラウズ

Unix の世界には、「すべてはファイルである」という古典的な格言があります。これが意味するのは、Unix オペレーティング システムでは、すべてのオブジェクトをファイルとして扱うことができ、ファイルを操作するためのインターフェイスを使用してオブジェクトを操作できるということです。 Linux も Unix に似たオペレーティング システムとして、この目標の達成に努めています。

仮想ファイル システムの概要

「すべてはファイルである」という目標を達成するために、Linux カーネルは中間層 仮想ファイル システム (仮想ファイル システム) を提供します。 オブジェクト指向プログラミング言語 (C/Java など) を使用したことがある場合は、

Interface

の概念に精通しているはずです。仮想ファイル システムは、一連の標準インターフェイスを定義するオブジェクト指向プログラミングのインターフェイスに似ています。開発者は、この一連のインターフェイスを実装するだけで、ファイルを操作するためのインターフェイスを使用してオブジェクトを操作できます。以下に示すように:

上の図の青い部分は、仮想ファイル システムの場所です。 细说 Linux 虚拟文件系统原理

上の図からわかるように、仮想ファイル システムは上位層アプリケーションに統合インターフェイスを提供します。ファイル システムが仮想ファイル システムのインターフェイスを実装している場合、上位層アプリケーションは

open()

read()write() などの関数を使用できます。 などの関数で操作します。 今日は、仮想ファイルシステムの原理と実装について紹介します。

仮想ファイルシステムの原理

仮想ファイル システムの原理を説明する前に、まず Java の例を紹介します。この Java の例を通じて、仮想ファイル システムの原理をより簡単に理解できます。

#Java の例

Java を使用してプログラムを作成したことがある場合は、仮想ファイル システムを簡単に理解できます。 Java のインターフェイスを使用して、仮想ファイル システムの定義をシミュレートします。 リーリー

上記では、

VFSFile

という名前のインターフェイスが定義されており、

open()read() write() などのいくつかのメソッドが定義されています。 など次に、このインターフェイスを実装するために Ext3File という名前のオブジェクトを定義します。 リーリー これで、次のように VFSFile インターフェイスを使用して

Ext3File

オブジェクトを操作できるようになります: <pre class="brush:js;toolbar:false;">public class Main() {   public static void main(String[] args) {     VFSFile file = new Ext3File();          int fd = file.open(&quot;/tmp/file.txt&quot;, 0);     ...   } } </pre> <p>从上面的例子可以看出,底层对象只需要实现 <code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin: 0 2px;font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;color: #10f5d6c">VFSFile 接口,就可以使用 VFSFile 接口相关的方法来操作对象,用户完全不需要了解底层对象的实现过程。

虚拟文件系统原理

上面的 Java 例子已经大概说明虚拟文件系统的原理,但由于 Linux 是使用 C 语言来编写的,而 C 语言并没有接口这个概念。所以,Linux 内核使用了一些技巧来模拟接口这个概念。

下面来介绍一下 Linux 内核是如何实现的。

1. file结构

为了模拟接口,Linux 内核定义了一个名为 file 的结构体,其定义如下:

struct file {
    ...
    const struct file_operations *f_op;
    ...
};

在 file 结构中,最为重要的一个字段就是 f_op,其类型为 file_operations 结构。而 file_operations 结构是由一组函数指针组成,其定义如下:

struct file_operations {
    ...
    loff_t (*llseek) (struct file *, loff_t, int);
    ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
    ...
    int (*open) (struct inode *, struct file *);
    ...
};

file_operations 结构的定义可以隐约看到接口的影子,所以可以猜想出,如果实现了 file_operations 结构中的方法,应该就能接入到虚拟文件系统中。

在 Linux 内核中,file 结构代表着一个被打开的文件。所以,只需要将 file 结构的 f_op 字段设置成不同文件系统实现好的方法集,那么就能够使用不同文件系统的功能。

这个过程在 __dentry_open() 函数中实现,如下所示:

static struct file *
__dentry_open(struct dentry *dentry, 
              struct vfsmount *mnt, 
              truct file *f, 
              int (*open)(struct inode *, struct file *), 
              const struct cred *cred)
{
    ...
    inode = dentry->d_inode;
    ...
    // 设置file结构的f_op字段为底层文件系统实现的方法集
    f->f_op = fops_get(inode->i_fop);
    ...
    return f;
}

设置好 file 结构的 f_op 字段后,虚拟文件系统就能够使用通用的接口来操作此文件了。调用过程如下:

细说 Linux 虚拟文件系统原理

2. file_operations结构

底层文件系统需要实现虚拟文件系统的接口,才能被虚拟文件系统使用。也就是说,底层文件系统需要实现 file_operations 结构中的方法集。

一般底层文件系统会在其内部定义好 file_operations 结构,并且填充好其方法集中的函数指针。如 minix文件系统 就定义了一个名为 minix_file_operationsfile_operations 结构。其定义如下:

// 文件:fs/minix/file.c

const struct file_operations minix_file_operations = {
    .llseek         = generic_file_llseek,
    .read           = do_sync_read,
    .aio_read       = generic_file_aio_read,
    .write          = do_sync_write,
    .aio_write      = generic_file_aio_write,
    .mmap           = generic_file_mmap,
    .fsync          = generic_file_fsync,
    .splice_read    = generic_file_splice_read,
};

也就是说,如果当前使用的是 minix 文件系统,当使用 read() 函数读取其文件的内容时,那么最终将会调用 do_sync_read() 函数来读取文件的内容。

3. dentry结构

到这里,虚拟文件系统的原理基本分析完毕,但还有两个非常重要的结构要介绍一下的:dentryinode

dentry 结构表示一个打开的目录项,当我们打开文件 /usr/local/lib/libc.so 文件时,内核会为文件路径中的每个目录创建一个 dentry 结构。如下图所示:

细说 Linux 虚拟文件系统原理

由于 /usr/local/lib/libc.so/tmp/libc.so 指向同一个文件,所以它们都使用同一个 inode 对象。

inode 结构保存了文件的所有属性值,如文件的创建时间、文件所属用户和文件的大小等。其定义如下所示:

struct inode {
    ...
    uid_t           i_uid;               // 文件所属用户
    gid_t           i_gid;               // 文件所属组
    ...
    struct timespec i_atime;             // 最后访问时间
    struct timespec i_mtime;             // 最后修改时间
    struct timespec i_ctime;             // 文件创建时间
    ...
    unsigned short  i_bytes;             // 文件大小
    ...
    const struct file_operations *i_fop; // 文件操作方法集(用于设置file结构)
    ...
};

我们注意到 inode 结构有个类型为 file_operations 结构的字段 i_fop,这个字段保存了文件的操作方法集。当用户调用 open() 系统调用打开文件时,内核将会使用 inode 结构的 i_fop 字段赋值给 file 结构的 f_op 字段。我们再来重温下赋值过程:

static struct file *
__dentry_open(struct dentry *dentry, 
              struct vfsmount *mnt, 
              truct file *f, 
              int (*open)(struct inode *, struct file *), 
              const struct cred *cred)
{
    ...
    // 文件对应的inode对象
    inode = dentry->d_inode;
    ...
    // 使用inode结构的i_fop字段赋值给file结构的f_op字段
    f->f_op = fops_get(inode->i_fop);
    ...
    return f;
}

总结

本文主要介绍了 虚拟文件系统 的基本原理,从分析中可以发现,虚拟文件系统使用了类似于面向对象编程语言中的接口概念。正是有了 虚拟文件系统,Linux 才能支持各种各样的文件系统。

以上がLinux仮想ファイルシステムの原理を詳しく説明するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlxlinux.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。