Linux虚拟文件系统

这一周主要学了文件系统的相关知识,通过学习基本上掌握了 linux 文件系统的结构,文件类型,以及读取模式等等,也学会怎么用命令简单的创建一个文件系统。

Linux 的文件系统主要有 ext2 ext3 ext4 ,在 windows 下一个分区会采用的一棵目录树来管理,而 linux 则只有一棵目录树,除了系统安装所在分区外,不管还有多少分区,什么样的文件系统,都只是目录树下的支干。根目录下的目录结构大致为 bin dev etc home lib sbin tmp root mnt proc usr var 等。 linux 中文件类型主要有五种:常规文件(用 - 表示)、目录文件(用 d 表示)、设备文件(块设备用 b 表示,字符设备用 c 表示)、管道文件(用 p 表示)、链接文件(用 l 表示)。存取权限根据用户类型分文件所有者、所有者所在的组、其他用户,操作模式只分成三种:读( 4 )、写( 2 )、执行( 1 ),根据用户类型正好分成三组操作模式共 9 位来表示,对应于三位的八进制。

本周学习用命令创建一个 ext2 文件系统的实例,由于文件系统较为复杂,并且可能需要随机并发读取文件,所以文件系统必须安装在块设备上,因为 linux 下设备也是一种特殊的文件,所以可以来模拟块设备文件,并在其上创建文件系统,最后用 mount 命令来挂载文件系统到某个目录下。详细代码如下:

sudo dd if=/dev/zero of=file.img bs=1k count=10000

/* 把输入文件 /dev/zero 拷贝到输出文件 file.img 中,输入输出的块大小为 1k, 拷贝的数量为 10000 块,这样 file.img 文件的总大小就是 10M */

losetup /dev/loop0 file.img

/* 使用 losetup 创建一个循环设备 loop0 ,并将其与 file.img 关联起来,这样就得到了一个近似的块设备 */

mke2fs -c /dev/loop0 10000

/* mke2fs 创建一个 10M ext2 文件系统 */

mkdir /mnt/point1

/* 创建一个挂载位置 */

 

mount -t ext2 /dev/loop0 /mnt/point1

/*mount linux 下的文件系统的挂载命令, -t 用来指定文件系统类型,后来跟上源路径和目的路径 */

ls /mnt/point1

/* 列出文件系统里的所有文件,显示结果文件系统中只有 lost+found 一个默认目录 */

linux 对于文件系统的支持较 windows 不仅仅是量的超跃,更是质的飞跃, linux 从最早期的 Minux 文件系统为起点,目前常见的文件系统几乎全部支持,这不禁让我们惊叹 linux 的伟大和包容,为了实现这一功能, linux 必须提供一个统一的接口平台,这就是 VFS( 虚拟文件系统 ) ,这是一个虚拟的文件系统,指其并不在磁盘中真实的存在,刚进入系统时只进行简单的初始化,只有当对文件进行操作时才会进行复杂的转换。

VFS 有四个主要的对象类型,也就是四种数据结构,它们分别是超级块对象( super_block )、索引节点对象( inode )、目录项对象( dentry )、文件对象( file ),这四个对象协同来唯一标识一个文件,并完成对文件的操作。这四个数据结构都有相对应的操作函数集,结构体定义大致示如下:

 

 

struct super_block

 

{

 

dev_t s_dev;/* 具体文件系统的块设备标识符。 */

 

unsigned long s_blocksize;/* 以字节为单位数据块的大小 */

 

unsigned char s_blocksize_bits; /* 块大小的值占用的位数,可以从 2^n= 大小来求得位数 */

 

struct list_head s_list; /* 指向超级块链表的指针,一个文件系统对应一节点,这样形成一个双向的循环链表 */

 

struct file_system_type *s_type;/* 指向文件系统的指针 */

 

struct super_operations *s_op;/* 指向具体文件系统的用于超级块操作的函数集合 */

 

...

 

};

 

超级块结构体用于获取已安装的文件系统的相关信息,并通过调用对应文件系统的函数集来完成一些操作,昨天我把系统所在的 ext4 分区的容量扩展了一些后再重启后便发现系统进不去了,想从光盘进入 livecd 后挂载这个分区拷贝一些重要的文件时却发现系统提示此分区的超级已损坏,看来对于 linux 分区最好不要随便的调节分区容量,以妨超级块损坏。

struct inode

 

{

 

struct list_head i_hash; /* 指向哈希链表的指针,采用 hash 链表的方法能使索引变得更高效 */

 

struct list_head i_list; /* 指向索引节点链表的指针,用于索引节点的遍历 */

 

struct list_head i_dentry;/* 指向目录项链表的指针 */

 

unsigned long i_ino;/* 索引节点号 */

 

umode_t i_mode;/* 文件的类型与访问权限 */

 

kdev_t i_rdev;/* 实际设备标识号 */

 

struct inode_operations *i_op; /* 指向对该节点进行操作的一组函数 */

 

struct super_block *i_sb;/* 指向该文件系统超级块的指针 */

 

atomic_t i_count;/* 当前使用该节点的进程数。计数为 0, 表明该节点可丢弃或被重新使用 */

 

struct file_operations *i_fop; /* 指向文件操作的指针 */

 

union{

 

struct minix_inode_info

 

struct Ext2_inode_info

 

...

 

}

 

索引节点用于提供内核对文件操作的所有信息,包括文件大小,存取时间,访问权限等等,这些信息是真实的存放在磁盘中的,这里涉及的文件泛指全部的文件类型,包括目录文件、设备文件或管道文件等,如用 i_devices i_bdev i_cdev 等等项来表示相关的设备文件。

struct dentry {

 

atomic_t d_count;/* 目录项引用计数器 */

 

unsigned int d_flags;/* 目录项标志 */

 

struct inode * d_inode; /* 与文件名关联的索引节点 */

 

struct dentry * d_parent;/* 父目录的目录项 */

 

struct list_head d_hash;/* 目录项形成的哈希表 */

 

struct list_head d_child;/* 父目录的子目录项所形成的链表 */

 

struct list_head d_subdirs;/* 该目录项的子目录所形成的链表 */

 

struct list_head d_alias;/* 索引节点别名的链表 */

 

struct dentry_operations *d_op; /* 操作目录项的函数 */

 

struct super_block * d_sb;/* 目录项树的根 ( 即文件的超级块 )*/

 

......

 

};

 

这个结构体的主要功能便是抽象出文件的逻辑关系,结构体本身并非实际的存放在磁盘上,当对文件进行操作时才会应运而生。 VFS 中目录看作文件,这个结构体中形成了两个主要的链,包括当前目录的兄弟链和儿子链,并且有指向你目录的指针,还有一个目录项树的根,也就是文件所在的文件系统,这样基本上就能定位任意一个文件了。

struct file

 

{

 

struct list_head f_list;/* 文件对象链表 */

 

struct dentry *f_dentry; /* 与文件相关的目录项对象 */

 

struct vfsmount *f_vfsmnt; /* 该文件所在的已安装文件系统 */

 

struct file_operations *f_op;/* 指向文件操作表的指针 */

 

mode_t f_mode;/* 文件的打开模式 */

 

loff_t f_pos;/* 文件的当前位置 */

 

unsigned short f_flags;/* 打开文件时所指定的标志 */

 

unsigned short f_count;/* 使用该结构的进程数 */

 

...

 

};

 

file 结构体主要的功能是为了标识文件的打开位置,这对共享文件的读写至关重要,这个结构体也与 dentry 结构体相似,并非实际的存放在磁盘上,只有在文件打开时才会产生这个结构体来描述文件的打开位置,第一个成员便是关键所有打开的文件。与其相关有 file_operations 结构体来描述对文件对象的操作,里面定义的全是函数指针成员,可以根据需要来为其赋于相关的函数,基本上用不到的则可以赋 NULL 。内核为每个进程提供了另外一个结构体(用户打开表),它是进程的私有数据,主要功能是来记录每个进程打开的文件,这里采用的并非常用的链表方法,而是用了指针数组的方法来存放某个进程所有打开文件的指针。

与文件系统相关的结构体还有 fs_struct ,它主要是用来关联进程所要访问的文件,这些文件可能不在同一个文件系统中,涉及的主要成员有 struct dentry * root, * pwd, * altroot;struct vfsmount * rootmnt, * pwdmnt, * altrootmnt; 分别用来标识文件的根目录项、当前目录项、替换目录项;已安装的根文件系统、当前文件系统、替换文件系统。

以上就是与文件系统相关的主要结构体的描述。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值