linux-文件系统

更新时间:2023-10-15 11:11:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

93443794.doc - 1 -

Linux的文件系统分析

摘要:本文先简要介绍Linux文件系统的整体结构及主要数据结构,然后着重介绍Linux对缓冲块(buffer)的管理,最后再给出系统调用sys_open的实现流程及相关的数据结构。

一.Linux文件系统简介

LINUX操作系统支持多个不同的文件系统:ext,ext2,minix,umsdos,ncp,iso9660,hpfs,msdos,xia,fat,vfat,proc,nfs,smb,sysv,affs以及ufs。每一种文件系统都有自己的组织结构和文件操作函数,相互之间差别很大。LINUX对上述文件系统的支持是通过虚拟文件系统VFS的引入而实现的。

1. 文件系统管理

LINUX文件系统管理的最上层模块是文件系统。系统启动时,必首先装入“根”文件系统,然后根据/etc/fstab中指定,逐个建立文件系统。此外,用户也可以通过mount、umount操作,随时安装或卸载文件系统。

当装入一个文件系统时,应首先向系统核心注册该系统及其类型。当卸载一个文件系统时,应向核心申请注销该系统及类型。文件系统的注册和注销反映在以vfsmntlist为链头, vfsmnttail为链尾,以vfsmount为节点的单向链表中。从链表的每一个vfsmount节点可找出一个已注册文件系统的信息。文件系统类型的注册和注销反映在以file_systems为链头,以file_system_type为节点的单向链表中。链表的每一个file_system_type节点描述一个已注册的文件系统类型。它们的数据结构如下描述:

int register_filesystem(struct file_system_type * fs) int unregister_filesystem(struct file_system_type * fs)

static struct file_system_type *file_systems = (struct file_system_type *) NULL; struct file_system_type { struct super_block *(*read_super) (struct super_block *, void *, int); /* read_super所指的函数用于读出该文件系统在外存的super_block */ const char name; / 文件系统的类型名,如ext2 */ int requires_dev; /* 支持文件系统的设备,proc文件系统不需要任何设备 */ struct file_system_type * next; /* 指向下一个节点 */ };

static struct vfsmount *vfsmntlist = (struct vfsmount ) NULL; / 头 */ static struct vfsmount *vfsmnttail = (struct vfsmount ) NULL; / 尾 */ static struct vfsmount *mru_vfsmnt = (struct vfsmount ) NULL; / 当前 */ struct vfsmount {

kdev_t mnt_dev; /* Device this applies to */ char mnt_devname; / 设备名,如/dev/had1 */ char mnt_dirname; / 安装目录名称 */ unsigned int mnt_flags; /* 设备标志,如ro */

93443794.doc - 2 -

struct semaphore mnt_sem; struct super_block mnt_sb; struct file mnt_quotas[MAXQUOTAS]; time_t mnt_iexp[MAXQUOTAS]; time_t mnt_bexp[MAXQUOTAS]; struct vfsmount mnt_next; };

/* 设备I/O操作时的信号量 */ / 指向超级块 */

/ 指向配额文件的指针 */ /* expiretime for inodes */ /* expiretime for blocks */ / pointer to next in linkedlist */

系统管理可从vfsmntlist开始,遍历整个文件系统链表,获得任何一个已安装文件系统的vfsmount。由vfsmount中的指针mnt_sb,获得该文件系统的super_block(super_blocks[]数组中一个元素,super_block将在下面介绍)。再从super_block得到具体信息,如s_type指向文件系统类型链表,s_mounted指向第一个VFS inode,s_covered指向安装点目录项的VFS inode。如下图所示:

vfsmntlistvfsmountmnt_devmnt_devnamemnt_dirnamemnt_flagsmnt_sb...nextsuper_blockfile_system_typeread_supernames_devs_blocksizes_types_flagss_covereds_mountedrequires_devnext...nextvilnttamfs...nextInodeInode图1

已挂文件系统节点、super_block结构和文件类型节点的关系图

2. 虚拟文件系统VFS

VFS是物理文件系统与服务之间的一个接口层,它对LINUX的每个文件系统的所有细节进行抽象,使得不同的文件系统在LINUX核心以及系统中运行的其他进程看来,都是相同的。严格说来,VFS并不是一种实际的文件系统。它只存在于内存中,不存在于任何外存空间。VFS在系统启动时建立,在系统关闭时消亡。

VFS的功能包括:

1) 记录可用的文件系统的类型;

2) 将设备同对应的文件系统联系起来; 3) 处理一些面向文件的通用操作;

4) 涉及到针对文件系统的操作时,VFS把他们映射到与控制文件、目录、以及

inode相关的物理文件系统。

当某个进程发布了一个面向文件的系统调用时,核心将调用VFS中相应的函

93443794.doc - 3 -

数,这个函数处理一些与物理结构无关的操作,并且把它重定向为真实文件系统中相应的函数调用,而这些函数调用则用来处理那些与物理结构相关的操作。下图显示了VFS与各文件系统之间的关系。

VFS InodeCacheVFSVFSDirectoryCacheMINIXEXT2UMSDOSBuffersCacheI/O设备驱动 图2 VFS与具体文件系统之间的关系

VFS的源代码集中在/usr/src/linux/fs目录下,关于它的数据结构的描述是在文件/usr/src/linux/include/linux/fs.h中。

3. VFS的super_block结构

VFS描述系统文件使用superblock和inode的方式。在系统初起时,所有被初始化的文件系统(file_system_type)都要向VFS(file_systems)登记。每种文件系统类型的读超级块子例程(read_super)必须识别该文件系统的结构并且将其信息

映射到一个VFS的超级块数据结构上。

struct super_block { kdev_t s_dev; /* 包含该文件系统的块设备号,*/ /*如0x0301代表设备/dev/hda1 */ unsigned long s_blocksize; /* 文件系统的块大小,以字节为单位 */ unsigned char s_blocksize_bits; /* 以2的次幂表示块的大小 */ unsigned char s_lock; unsigned char s_rd_only; unsigned char s_dirt; /* 已修改标志 */ struct file_system_type *s_type; /* 指向对应的file_system_type结构 */ struct super_operations *s_op; /* 指向一组操作该文件系统的函数 */ struct dquot_operations *dq_op; unsigned long s_flags; unsigned long s_magic;

93443794.doc - 4 -

};

unsigned long s_time;

struct inode * s_covered; /* 指向安装点目录项的inode节点,*/ /* 根文件系统的VFS超级块没有此指针 */ struct inode * s_mounted; /* 指向被安装文件系统的第一个inode节点 */ struct wait_queue * s_wait; /* 在该超级块上的等待队列 */ union { /* 各类文件系统的特定信息 */ struct ext2_sb_info ext2_sb; /* ext2文件系统的超级块 */ } u;

为了文件系统的性能,设备上的超级块(或FAT表等索引信息)必须驻留内存空间。VFS的super_block数据结构即提供了这样的内存空间。其中,聚合类型成员super_block.u是实现的关键。例如,ext2类型的文件系统一旦安装,磁盘上的超级块信息即会复制到一个ext2_sb_info结构,super_block.u.ext2_sb将指向该结构。

VFS超级块包含了一个指向文件系统中的第一个inode的指针s_mounted。对于根文件系统,它就是代表根目录的inode节点(inode结构将在下文描述)。

VFS超级块也包含一个指向该文件系统安装点的inode(此inode属于另一文件系统)的指针s_covered。对于根文件系统,s_covered无效。

利用VFS超级块的s_mounted 和s_covered,以及inode,可以构造包容所有已安装文件系统的树型目录结构,如下图所示:

root下挂文件系统i_sb安装点inodei_mount文件系统的超级块s_mounteds_covered图3 已安装文件系统的树形目录结构

4. VFS的inode结构

文件系统由子目录和文件构成。每个子目录或文件只能由唯一的inode描述。

inode 是LINUX管理文件系统的最基本单位,也是文件系统连接任何子目录、任何文件的桥梁。

93443794.doc - 5 -

struct inode { kdev_t i_dev; /* 文件所在设备的设备号,第一个IDE硬盘为0x0301 */ unsigned long i_ino; /* 外存inode的节点号,*/ /* (i_dev,i_ino)在VFS中是唯一的 */ umode_t i_mode; /* 表示文件类型以及存取权限 */ nlink_t i_nlink; /* 连接到该文件的link数 */ 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; /* 以字节为单位的块大小,*/ /* 一般为1024字节 */ unsigned long i_blocks; /* 文件块数 */ unsigned long i_version; unsigned long i_nrpages; /* 文件在内存中所占页数 */ struct semaphore i_sem; /* 信号量 */ struct inode_operations *i_op; /* 指向一组针对该文件的操作函数 */ struct super_block *i_sb; /* 指向内存中VFS的超级块 */ struct wait_queue *i_wait; /* 在该文件上的等待队列 */ struct file_lock *i_flock; struct vm_area_struct *i_mmap; struct page *i_pages; /* 由文件占用页面构成的单向链,*/ /* 通过它可访问内存中的文件数据 */ struct dquot *i_dquot[MAXQUOTAS]; struct inode *i_next, *i_prev; /* inode资源管理中使用的链表指针 */ struct inode *i_hash_next, *i_hash_prev; /* inode cache的链表指针 */ struct inode *i_bound_to, *i_bound_by; struct inode *i_mount; /* 指向下挂文件系统的inode的根目录 */ unsigned long i_count; /* 引用记数,0表示是空闲inode */ unsigned short i_flags; unsigned short i_writecount; unsigned char i_lock; /* 对inode加锁标志 */ unsigned char i_dirt; unsigned char i_pipe; unsigned char i_sock; unsigned char i_seek; unsigned char i_update; unsigned char i_condemned; union { /* 各类文件系统inode的特定信息 */ struct ext2_inode_info ext2_i;

本文来源:https://www.bwwdw.com/article/ygif.html

Top