Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2929524
  • 博文数量: 401
  • 博客积分: 12926
  • 博客等级: 上将
  • 技术积分: 4588
  • 用 户 组: 普通用户
  • 注册时间: 2009-02-22 14:51
文章分类

全部博文(401)

文章存档

2015年(16)

2014年(4)

2013年(12)

2012年(82)

2011年(98)

2010年(112)

2009年(77)

分类: LINUX

2010-11-24 18:09:07

1.1.              基本概念

1、 一块磁盘(块设备),首先要按照某种文件系统(如 NTFS)格式进行格式化,然后才能在其上进行创建目录、保存文件等操作。

 Linux 中,有“安装”文件系统和“卸载”文件系统的概念。

一块经过格式化的“块设备”(不管是刚刚格式化完的,没有创建任何名录和文件;还是已经创建了目录和文件),只有先被“安装”,才能融入 Linux 的文件系统中,用户才可以在它上面进行正常的文件操作。

2、 Linux 把目录或普通文件,统一看成“目录节点”。通常一个“目录节点”具有两个重要属性:名称以及磁盘上实际对应的数据。本文中,“目录节点”有时简称为“节点”

“符号链接”是一种特殊的目录节点,它只有一个名称,没有实际数据。这个名称指向一个实际的目录节点。

3、 “接口结构”:在 内核代码中,经常可以看到一种结构,其成员全部是函数指针,例如:

struct file_operations {

struct module *owner;

loff_t (*llseek) (struct file *, loff_t, int);

ssize_t (*read) (struct file *, char *, size_t, loff_t *);

ssize_t (*write) (struct file *, const char *, size_t, loff_t *);

int (*readdir) (struct file *, void *, filldir_t);

unsigned int (*poll) (struct file *, struct poll_table_struct *);

int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);

int (*mmap) (struct file *, struct vm_area_struct *);

int (*open) (struct inode *, struct file *);

int (*flush) (struct file *);

int (*release) (struct inode *, struct file *);

int (*fsync) (struct file *, struct dentry *, int datasync);

int (*fasync) (int, struct file *, int);

int (*lock) (struct file *, int, struct file_lock *);

ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);

ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);

ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);

unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);

};

这种结构的作用类似与 C++ 中的“接口类”,它是用 C 语言进行软件抽象设计时最重要的工具。通过它,将一组通用的操作抽象出来,核心的代码只针对这种“接口结构”进行操作,而这些函数的具体实现由不同的“子类”去完成。

以这个 file_operations“接口”为例,它是“目录节点”提供的操作接口。不同的文件系统需要提供这些函数的具体实现。

本文中,“接口结构”有时简称“接口”。

1.2.              虚拟文件系统

Linux 通过虚拟文件系统 VFS 来支持不同的具体的文件系统,那么 VFS 到底是什么?

从程序员的角度看,我认为 VFS 就是一套代码框架(framework,它将用户与具体的文件系统隔离开来,使得用户能够通过这套框架,以统一的接口在不同的具体的文件系统上进行操作。

这套框架包括:

1、 为用户提供统一的文件和目录的操作接口,如 open, read, write

2、 抽象出文件系统共有的一些结构,包括“目录节点”inode、“超级块”super_block 等。

3、 面向具体的文件系统,定义一系列统一的操作“接口”,  file_operations, inode_operations, dentry_operation,具体的文件系统必须提供它们的实现。

4、 提供一套机制,让具体的文件系统融入 VFS 框架中,包括文件系统的“注册”和“安装”

5、 实现这套框架逻辑的核心代码


我对文件系统的学习,实际上就是学习虚拟文件系统这套框架是如何实现的。


2.   核心数据结构

数据结构是代码的灵魂,要分析一个复杂的系统,关键是掌握那些核心的数据结构,这包括:

1、 弄清数据结构的核心功能。一个数据结构通常具有比较复杂的成员,此外,还有一些成员用于建立数据结构之间的关系。如果要一个个去理解,就会陷入细节。

2、 弄清数据结构之间的静态关系

3、 弄清数据结构之间是如何建立起动态的关系的

本文重点分析文件系统中的关键数据结构以及它们之间的关系。


2.1.              inode  file_operations

1、 inode 用以描述“目录节点” ,它描述了一个目录节点物理上的属性,例如大小,创建时间,修改时间、uidgid 

2、 file_operations 是“目录节点”提供的操作“接口”。它包括 open, read, wirte, ioctl, llseek, mmap 等操作。

3、 一个 inode 通过成员 i_fop 对应一个 file_operations

4、 打开文件的过程就是寻找 “目录节点”对应的 inode 的过程

5、 文件被打开后,inode  file_operation 都已经在内存中建立,file_operations 的指针也已经指向了具体文件系统提供的函数,此后都文件的操作,都由这些函数来完成。


例如打开了一个普通文件 /root/file,其所在文件系统格式是 ext2,那么,内存中结构如下:

2.2.              目录节点入口dentry

本来,inode 中应该包括“目录节点”的名称,但由于符号链接的存在,导致一个物理文件可能有多个文件名,因此把和“目录节点”名称相关的部分从 inode 中分开,放在一个专门的 dentry 结构中。这样:

1、 一个dentry 通过成员 d_inode 对应到一个 inode上,寻找 inode 的过程变成了寻找 dentry 的过程。因此,dentry 变得更加关键,inode 常常被 dentry所遮掩。可以说, dentry 是文件系统中最核心的数据结构,它的身影无处不在。

2、 由于符号链接的存在,导致多个 dentry 可能对应到同一个 inode 


例如,有一个符号链接 /tmp/abc 指向一个普通文件 /root/file,那么 dentry  inode 之间的关系大致如下:


阅读(1568) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~