Linux文件系统学习笔记

文件的存储

  • 分两部分

纯数据区

  • 文件真正的数据存储区、基本存储单位为block

元数据区

  • 文件属性:磁盘中的存储位置、文件长度等信息
  • 时间戳:创建时间、修改时间
  • 读写权限:使用read/write系统调用时,要首先要进行权限检查
  • 所属组、所有者
  • 链接数

文件索引节点 inode

用来存储文件信息

  • inode:每个文件使用一个inode结构体来描述
  • 每个inode有固定编号、有单独的存储空间
  • 每个inode的大小为128/256B
  • Linux系统根据inode来查找文件的存储位置

TIPS

  • 查看文件的inode信息:$ stat xx.c
  • 查看某个分区的inode总数:$ df -i
  • 查看inode大小:$ dumpefs -h /dev/sda1

在这里插入图片描述

data block

数据块(逻辑块)

  • 格式化磁盘时划分的文件系统的最小逻辑读写单位
  • 每个block都有自己的编号,inode中存放文件的block地址信息
  • 一个block一般是扇区或页的整数倍:1K/2K/4K

TIPS

  • 查看某个分区的block信息:$ df

在这里插入图片描述

超级块super block

  • 记录整个文件系统信息
  • 一个inode、block的大小
  • inode使用情况:已使用数量、未使用数量
  • block使用情况:已使用数量、未使用数量
  • 文件系统挂载情况
  • 文件系统的挂载时间、最后一次写入数据、检验磁盘的时间
  • 当文件系统挂载时,这部分信息会加载到内存,并常驻内存

磁盘格式化

两种格式化

物理格式化

  • 磁盘在使用前要进行分区和格式化:MBR中存放分区信息、开机代码
  • 出厂前厂家已经做好的工作:划分磁道、扇区

逻辑格式化

  • 使用格式化工具,在磁盘上安装文件系统
  • 将磁盘划分为不同的block
  • 将磁盘划分为不同的区段

在这里插入图片描述

不同的区段

  • boot sector:引导扇区
  • Superblock:记录文件系统的整体信息、inode和block信息

block group

  • 每个block group都有一个group descriptor,聚集存储在分区开头位置
  • block bitmap:记录block的使用情况,哪些在使用,哪些是空的
  • inode bitmap:记录inode的使用情况
  • inode table、data block

在这里插入图片描述

块组

block group

  • 一个分区在格式化时,可以划分为多个block group
  • 每个block group包含block bitmap、 inode bitmap、 inode table、 data block
  • 每个block bitmap大小为一个block,每bit表示一个block
  • 每个inode bitmap大小为一个block,每一个bit表示一个inode

group descriptor

  • 存储在superblock的后面
  • 有一个block指针,指向block bitmap
  • 有一个block指针,指向inode bitmap
  • 有一个block指针,指向inode table
  • group descriptor信息存储在superblock中: group descriptor总数等信息

在这里插入图片描述

目录和目录项

目录

  • 目录是一个文件,有自己的inode,在inode中将该文件类型标记为“目录”
  • 目录存储在data block中
  • 目录本质上是一个表格:由若干个目录项组成
  • 一个目录下面可以多个文件:文件名和文件对应的inode
  • 一个目录文件有多个子目录:目录名和其对应的inode
  • 多个子目录构成树状的文件系统结构

目录项

  • 一个目录项由文件名和inode编号组成,根据inode编号可以找到inode table中真正的inode节点
  • 目录项存储在data block中

在这里插入图片描述

文件路径

构成

  • 由各个目录、子目录构成
  • 各个路径构成树状结构的文件系统

分类

  • 相对路径
  • 绝对路径

绝对路径

根目录

  • 绝对路径的参考起点
  • Linux内核中的“/”
  • Windows系统中的盘符
  • 文件系统预留的inode编号:2

相对路径

当前目录

  • 相对路径的参考起点
  • . :当前目录的硬链接
  • … :上级目录的硬链接
  • 根目录下的.和…
  • 查看当前目录的inode编号:$ ls –i –d .

小结

  • 一个目录下可以包含多个文件、或者嵌套多个子目录
  • 各级目录构成一个路径,应用程序根据该路径来找到文件
  • 路径分为绝对路径和相对路径
  • 路径的本质:各级目录文件中的目录构成的一个inode链

文件系统的挂载

基本原理

  • 一个磁盘格式化、安装文件系统后,可以通过文件接口访问存储空间
  • 用户通过路径名来访问文件
  • 挂载:让磁盘与Linux根文件系统某个目录建立关联、加入全局文件系统树
  • 挂载点(mount point)是进入该挂载设备文件系统的入口

实验

  • mount --bind udisk/ mnt/
    在这里插入图片描述
    在这里插入图片描述

挂载过程

  • 结构体:vfsmount\superblock
  • 每个挂载的文件系统,VFS都会创建一个vfsmount、super_block对象
  • 该对象描述了文件系统mount的所有信息
  • 父文件系统的挂载点:vfsmount->mnt_mountpoint = /mnt
  • 子文件系统的根目录:vfsmount->mnt_root = superblock->s_root
  • 初始化好vfsmount对象后,将该对象添加到VFSMOUNT hash table(哈希表) 中。

文件路径解析

在这里插入图片描述

目录项

  • 若目录项dentry标记为DCACHE_MOUNTED,路径解析时对该目录/mnt项屏蔽
  • 计算该目录的HASH值,根据值去VFSMOUNT hash table查找对应的vfsmount对象
  • 根据vfsmount->mnt_root,找到子文件系统的根目录
  • 查找子文件系统指定目录下的文件

文件系统类型

基于操作系统

基于Linux/android

  • ext/ext2/ext3/ext4、XFS、brtfs、iso9660、JFFS/JFFS2
  • minix、proc、NFS、SMB、swap
  • CRAMFS、yaffs、yaffs2、UBIFS

基于Windows

  • FAT16/FAT32
  • NTFS

基于Mac OS X

  • HFS

Linux下的文件系统

按存储介质划分

基于磁盘/Flash
  • Ext2/ext3/ext4
  • JFFS2、UBIFS、CRAMFS
  • 基于Flash的文件系统一般基于MTD驱动:坏块管理、磨损均衡
基于内存
  • ramdisk : ramfs、tmpfs
其它特殊文件系统
  • procfs、sysfs
  • NFS:network file system
  • devfs

文件系统选择

性能指标

  • 挂载时间
  • IO性能:顺序/随机读写能力、IO等待时间、大/小文件读写能力
  • 资源利用率:存储空间利用率、CPU利用率
  • 功耗

嵌入式文件系统

组合文件系统

  • 根据存储数据不同划分不同分区:系统、配置、数据、多媒体数据
  • 内存文件系统:ramdisk、proc
  • 特殊文件系统:devfs、sysfs

虚拟文件系统(VFS)

  • visual file system
  • 基于内核和存储设备之间的抽象层
  • 向上:统一封装了不同设备、文件系统的读写接口:系统调用API
  • 向下:新的设备、文件系统添加到Linux内核,实现VFS的接口即可
  • Linux内核支持60+种不同类型的文件系统

在这里插入图片描述

VFS的对象类型

对象属性

  • super_block:已经安装的具体的文件系统
  • inode:代表一个具体的文件
  • dentry:目录项,目录项路径的组成部分
  • file:进程打开的文件

对象方法

  • super_operations:alloc_inode、write_inode、destroy_inode
  • inode_operations:link、mknod、mkdir、rename、create
  • dentry_operations:d_hash、d_compare、d_delete、d_release
  • file_operations:read、write、open、close、fsync、mmap

通过OOP理解VFS

VFS中的面向对象思想

  • 封装:file->file_operations
  • 继承:write_inode、ext2_write_inode
  • 多态:callback

文件的存储

  • 磁盘:扇区、簇、superblock、block、inode、dentry
  • Flash:页、块、block、inode、dentry
  • VFS:统一操作接口
  • 系统调用接口:open、close、read、write、fsync
  • C标准库函数:fopen、fclose、fread、fwrite、fsync

程序中如何操作文件

文件描述符

  • Linux进程使用文件描述符(file descriptors,简称fd)来操作文件
  • int fd = open (“/home/wit/hello.txt”, O_WRONLY, 0666);
  • read (fd, buf, 100);
  • 结构体files_struct
  • 用来表示一个进程打开的文件列表
struct files_struct { 
	atomic_t count; 
	bool resize_in_progress; 
	wait_queue_head_t resize_wait; 
	struct fdtable __rcu *fdt; 
	struct fdtable fdtab; int next_fd; 
	unsigned long close_on_exec_init[1];
	unsigned long open_fds_init[1];
	unsigned long full_fds_bits_init[1]; 
	struct file __rcu * fd_array[NR_OPEN_DEFAULT]; 
};

文件

struct file {
	union {
		struct llist_node fu_llist;
		struct rcu_head fu_rcuhead;
	} f_u; //所有打开的文件构成一个系统级的全局双链表
	struct path f_path;
	struct inode *f_inode; //inode节点
	const struct file_operations *f_op; //该文件的读写方法
	spinlock_t f_lock;
	atomic_long_t f_count;
	unsigned int f_flags;
	fmode_t f_mode; //打开模式
	struct mutex f_pos_lock;
	loff_t f_pos; //文件当前位置
	struct fown_struct f_owner;
	const struct cred *f_cred;
	struct file_ra_state f_ra;
	u64 f_version;
	void *private_data;
	struct address_space *f_mapping;
};

一个进程打开的文件

在这里插入图片描述

C语言中的文件指针FILE*

对文件描述符的封装

  • 文件描述符:fd
  • 文件位置:f_fops
  • 缓冲区
  • 文件标志:f_mod
typedef struct _IO_FILE FILE;
	struct _IO_FILE {
	int _flags;
	char* _IO_read_ptr; /* Current read pointer */
	char* _IO_read_end; /* End of get area. */
	char* _IO_read_base; /* Start of putback+get area. */
	char* _IO_write_base; /* Start of put area. */
	char* _IO_write_ptr; /* Current put pointer. */
	char* _IO_write_end; /* End of put area. */
	char* _IO_buf_base; /* Start of reserve area. */
	char* _IO_buf_end; /* End of reserve area. */
	char *_IO_save_base; /* Pointer to start of non-current get area. */
	char *_IO_backup_base; /* Pointer to first valid character of backup area */
	char *_IO_save_end; /* Pointer to end of non-current get area. */
	struct _IO_marker *_markers;
	struct _IO_FILE *_chain;
	int _fileno;
	_IO_off_t _old_offset; /* This used to be _offset but it's too small. */
};

标准流

文件描述符用途POSIX名称stdio流
0标准输入STDIN_FILENOstdin
1标准输出STDOUT_FILENOstdout
2标准错误STDERR_FILENOstderr

硬链接与软链接

链接

  • Linux下一种文件共享的方式,类似于Windows下的快捷方式
  • 一个文件使用多个别名:多个文件名共享一个inode
    在这里插入图片描述

硬链接

  • 硬链接和文件有相同的inode和datablock
    在这里插入图片描述

软链接

  • 软链接是一个普通文件,文件内容为:指向文件的路径名
  • 有自己的inode编号和data block、文件权限、属性…
  • 删除软链接不会影响到其指向的文件本身
    在这里插入图片描述

硬链接与软链接区别

硬链接

  • 只能对存在的文件创建硬链接
  • 不能对目录创建硬链接
  • 创建硬链接不能跨越文件系统分区

软链接

  • 可以对不存在的文件或目录创建软链接
  • 可以对目录创建软链接
  • 可以跨越文件系统分区创建软链接

命令

FS相关

  • mount
  • mkdir/rmdir/chmod/chown/
  • df、du、wc

磁盘管理

  • 统计磁盘使用率:$ df -h
  • 统计目录:$ du

文件统计

  • 当前目录下的C文件个数: $ find . -name “*.c” | wc -l
  • 当前目录下(包括子目录)的文件个数:$ ls –lR | grep “^-” | wc –l
  • 一个项目的总目录个数:$ ls –lR | grep “^d” | wc –l
  • 一个项目的代码总行数:$ find . -name “*.c” |xargs cat | wc -l

磁盘格式化及挂载

格式化、分区

fdisk /dev/sdb
按m显示菜单
按n添加分区
按p设置为主分区,e设置为扩展分区
输入分区号
第一个扇区大小(默认2048,2k)
...一路默认
按w保存

ls /dev/sdb*

安装文件系统

在这里插入图片描述

mkfs.ext4 /dev/sdb1

挂载

mount -t ext4/ dev/sdb1 /mnt

恢复删除的文件

rm命令

文件删除的背后

  • 并没有真正删除数据,当inode的链接计数>1时
  • 仅删除了文件名和inode之间的关联:清除了目录项中inode指针信息,

真正的文件删除

  • 当inode的链接计数为1时
  • 将目录项中的文件名和inode对应关系删除
  • 将该文件inode中的block指针删除
  • 在inode bitmap中将该文件的inode标记为未用
  • 将block bitmap中将该文件的data block标记为未用
  • ext日志文件系统:把删除文件的inode信息和文件名写入日志

在这里插入图片描述

恢复删除的文件

  • apt-get install extundelete
  • extundelete --inode 2 /dev/sdb1
  • extundelete /dev/sdb1 --restore-file /home/wit/hello.c
  • extundelete /dev/sda1 --restore-inode 1122
  • extundelete /dev/sdb1 --restore-directory /home/wit/test
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值