Linux文件系统学习(未完)

1. Linux文件系统的特点与类别

1.1 特点

Linux系统中,文件组织在一个统一的树形目录结构中,整个文件系统有一个根“/”(文件夹),然后以每个目录(文件夹)作为分叉,叶子节点作为文件,如下图所示:
Linux典型文件结构
简单介绍一下:
/:所有文件的根目录
/bin:存放常用用户命令
/boot:存放内核系统启动所需文件
/dev:存放设备文件,如声卡文件,磁盘文件等
/etc:存放系统管理和配置文件目录
/home:用户主目录的基点目录,默认情况每个用户主目录都设在该目录下,如默认情况下用户user01 的主目录是/home/user01
/lib:存放标准程序设计库目录,又叫动态链接共享库目录,目录中文件类似windows里的后缀名为 dll的文件
/media:其他文件系统的挂载点
/proc:虚拟目录,是系统内存的映射,可直接访问这个目录来获取系统信息
/root:超级用户主目录
/sbin:系统管理程序
/sys:存放设备相关的系统信息
/usr:最庞大的目录,存放应用程序和文件目录
/tmp:临时文件
/var:存放系统产生的经常变化文件的目录,例如打印机、邮件等假脱机目录、日志文件、格式化后的手 册页以及一些应用程序的数据文件等
/usr/games:存放游戏
/usr/src:存放程序源代码
/usr/man:存放帮助文件

一般除了树形结构特点外,还具有如下特点:

  • 文件是无结构的字符流式文件
  • 文件可以动态增长或减少
  • 可以设置权限
  • 外部设备(磁盘,键盘,鼠标),都被看做文件,可以通过文件系统隐蔽掉设备特性

1.2文件类型

Linux文件可以分为6种类型:

  • 普通文件‌:最常见的文件类型,包含文本文件、数据文件等,可以直接读取内容
  • 目录文件‌:用于组织和管理其他文件和子目录,类似于Windows中的文件夹
  • 字符设备文件‌:用于与字符设备(如键盘、鼠标)进行通信
  • 块设备文件‌:用于与块设备(如硬盘、USB存储设备)进行数据交换
  • 符号链接文件‌:类似于Windows中的快捷方式,指向另一个文件或目录
  • 套接字文件‌:用于进程间通信,允许不同进程通过文件系统进行数据交换

2. Linux之虚拟文件系统

2.1 框架

Linux 提供了一种称为“虚拟文件系统”(Virtual File System, 简称 VFS)的软件抽象层,它允许 Linux 支持多种不同类型的文件系统。VFS 在用户空间和各种文件系统之间提供了一个抽象层,使得用户空间可以通过标准的系统调用来访问不同的文件系统,而不需要关心底层文件系统的具体实现细节。

2.1.1主要作用:

‌抽象层‌:VFS为底层具体的文件系统提供了一个抽象层,使得用户程序无需关心文件系统的具体实现。
‌统一接口‌:提供了一套统一的文件操作接口(如read、write、open等),使得应用程序可以使用相同的系统调用来访问不同类型的文件系统。
支持多种文件系统‌:VFS支持多种文件系统,包括本地文件系统(如ext4、XFS)、网络文件系统(如NFS)以及特殊文件系统(如procfs、sysfs)

系统调用图

2.1.2 VFS核心的四个数据结构

super_block :超级块,用于描述具体的文件系统信息
inode:索引节点,用以描述一个文件的元信息,如文件大小、权限、拥有者等,每个文件均对应一个inode
dentry:目录项结构,它的出现就是为了性能,一般在磁盘中是没有对应的结构的
file:文件结构,代表与进程交互过程中被打开的一个文件

2.1.2.1 超级块

一个具体的文件系统,如ext2、ext4等,都会对应一个超级块结构。内核也是通过扫描这个结构的信息来确定文件系统的大致信息,以下为其在内核源码中的部分定义(选自Linux 5.19,后续一样)

struct super_block {struct list_head	s_list;		// 指向超级块链表的指针dev_t			s_dev;		/* 块设备的具体标识号 */unsigned char		s_blocksize_bits;unsigned long		s_blocksize; // 文件系统中的数据块大小loff_t			s_maxbytes;	/* 允许的最大文件的大小 */struct file_system_type	*s_type; // 具体的文件系统类型const struct super_operations	*s_op; // 用于超级块操作的函数集合const struct quotactl_ops	*s_qcop; // 限额操作的函数集合unsigned long		s_flags; // 安装表示unsigned long		s_magic; // 幻数 一般可以用于表示唯一的文件系统struct dentry		*s_root; //根dentrystruct rw_semaphore	s_umount; // 同步读写int			s_count; // 超级块的使用计数atomic_t		s_active;void			*s_fs_info;	/* 文件系统的隐私信息 *//* c/m/atime限制 */time64_t		   s_time_min;time64_t		   s_time_max;unsigned int		s_max_links;fmode_t			s_mode;// 默认的目录项操作集合const struct dentry_operations *s_d_op; /* default d_op for dentries */// 虽然链接数目为0 但仍然被引用atomic_long_t s_remove_count;// 没有被使用的dentry、inode会被加入这个struct list_lru		s_dentry_lru;struct list_lru		s_inode_lru;struct rcu_head		rcu;/* s_inode_list_lock protects s_inodes */spinlock_t		s_inode_list_lock ____cacheline_aligned_in_smp;struct list_head	s_inodes;	/* 所有的索引节点 由前面的锁进行保护 */spinlock_t		s_inode_wblist_lock;struct list_head	s_inodes_wb;	/* writeback inodes */......
} __randomize_layout;

超级块的操作函数集合:

struct super_operations {//给超级块分配索引节点struct inode *(*alloc_inode)(struct super_block *sb); // 销毁索引节点void (*destroy_inode)(struct inode *);// 检查atime的更新情况void (*dirty_inode) (struct inode *, int flags);// 写入一个inode到磁盘中int (*write_inode) (struct inode *, struct writeback_control *wbc);// 删除一个inodeint (*drop_inode) (struct inode *);//在链接数目为0时会进行释放void (*evict_inode) (struct inode *);// 释放超级块所占用的内存void (*put_super) (struct super_block *);......
};

这些集合的函数会由具体的文件系统进行实现,没有实现的会被置为NULL

2.1.2.2 索引节点

Linux中是视一切为文件,一个文件就会有对应的inode,文件包含了常规文件、目录等。在需要时,在磁盘中的inode会被拷贝到内存中,修改完毕后会被写回到磁盘中。一个inode会被指向多个目录项索引(硬链接等)

以下为它在内核中的部分源码定义:

struct inode {umode_t			i_mode; unsigned short		i_opflags;kuid_t			i_uid; // 文件所属的用户kgid_t			i_gid; // 文件所属的组unsigned int		i_flags;const struct inode_operations	*i_op; // 索引节点操作函数集struct super_block	*i_sb; // 文件所在文件系统的超级块struct address_space	*i_mapping;/* Stat data, not accessed from path walking */unsigned long		i_ino; // 索引号/** Filesystems may only read i_nlink directly.  They shall use the* following functions for modification:**    (set|clear|inc|drop)_nlink*    inode_(inc|dec)_link_count*/union {const unsigned int i_nlink; // 链接数目unsigned int __i_nlink;};dev_t			i_rdev; // 文件所在的设备号loff_t			i_size; // 文件大小struct timespec64	i_atime;// 最后的访问时间struct timespec64	i_mtime; // 最后修改时间struct timespec64	i_ctime; // 最后改变时间spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */unsigned short          i_bytes; // 使用的字节数/* Misc */unsigned long		i_state;struct rw_semaphore	i_rwsem; // 读写信号量struct hlist_node	i_hash; // 哈希值 负责提高查找效率struct list_head	i_io_list;	/* backing dev IO list */struct list_head	i_lru;		/* inode LRU list  未使用的inode*/struct list_head	i_sb_list; // 链接一个文件系统中的inode链表struct list_head	i_wb_list;	/* backing dev writeback list */union {struct hlist_head	i_dentry; // 所属的目录项struct rcu_head		i_rcu;};atomic64_t		i_version; // 索引节点版本号atomic_t		i_count; // 引用计数atomic_t		i_writecount; // 写计数// 文件操作函数集合union {const struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */void (*free_inode)(struct inode *);};struct address_space	i_data;struct list_head	i_devices;void			*i_private; /* 文件与设备的私有指针 */......
} __randomize_layout;

索引节点的函数操作集合:

struct inode_operations {// 查找指定文件的dentrystruct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);//根据inode所描述的文件类型,如果是目录,则会创建一个inode,不是则不会调用int (*create) (struct user_namespace *, struct inode *,struct dentry *,umode_t, bool);//在指定目录下创建一个子目录int (*mkdir) (struct user_namespace *, struct inode *,struct dentry *,umode_t);//从inode所描述的目录中删除一个子目录时,会被调用int (*rmdir) (struct inode *,struct dentry *);......
} ____cacheline_aligned;

2.1.2.3 目录项结构

它的出现主要是为了查找性能,只存在于内存中,而不存在于磁盘中。这提供了一种非常快的查询机制来将一个路径名称(文件名称)转换为特定的目录项对象。

以下为它在内核中的部分源码定义:

struct dentry {/* RCU lookup touched fields */unsigned int d_flags;		/* protected by d_lock */seqcount_spinlock_t d_seq;	/* per dentry seqlock */struct hlist_bl_node d_hash;	/* lookup hash list 哈希列表*/struct dentry *d_parent;	/* parent directory 父目录 */struct qstr d_name; struct inode *d_inode;		/*与目录关联的inode Where the name belongs to - NULL is* negative */unsigned char d_iname[DNAME_INLINE_LEN];	/* small names *//* Ref lookup also touches following */struct lockref d_lockref;	/* per-dentry lock and refcount */const struct dentry_operations *d_op; // 目录项操作struct super_block *d_sb;	/* 目录项所属文件系统的超级块 The root of the dentry tree */union {struct list_head d_lru;		/* LRU list 未使用目录项以LRU算法链接的链表*/wait_queue_head_t *d_wait;	/* in-lookup ones only */};struct list_head d_child;	/* child of parent list 加入到父目录的d_subdirs */struct list_head d_subdirs;	/* our children 子目录 *//** d_alias and d_rcu can share memory*/union {struct hlist_node d_alias;	/* inode alias list */struct hlist_bl_node d_in_lookup_hash;	/* only for in-lookup ones */struct rcu_head d_rcu;} d_u;
} __randomize_layout;

目录项的函数操作集合:

struct dentry_operations {// 检查当前目录项是否还有效int (*d_revalidate)(struct dentry *, unsigned int);// 较弱形式的校验int (*d_weak_revalidate)(struct dentry *, unsigned int);// int (*d_hash)(const struct dentry *, struct qstr *);// 引用计数为0时删除dentry(dput调用)int (*d_delete)(const struct dentry *);// 释放所占有的数据void (*d_release)(struct dentry *);//当dentry失去inode时调用,void (*d_iput)(struct dentry *, struct inode *);
......
} ____cacheline_aligned;

2.1.2.4 文件结构

当一个进程打开一个文件时,该文件就是用此文件结构进行描述的,如文件的读写模式、读写偏移量、所属inode等信息。这个文件结构会被进程的文件描述符表所存放。

以下为它在内核中的部分源码定义:

struct file {union {struct llist_node	fu_llist; // 文件系统中被打开的文件对象(单个进程所打开的文件会被维护在另一个结构中 files_struct)struct rcu_head 	fu_rcuhead; } f_u;struct path		f_path;struct inode		*f_inode;	/* cached value  被缓存的值 所属的inode吧*/const struct file_operations	*f_op; // 文件操作指针/** Protects f_ep, f_flags.* Must not be taken from IRQ context.*/spinlock_t		f_lock;    // 自旋锁atomic_long_t		f_count; // 引用计数器unsigned int 		f_flags; // 打开文件所引用的标志fmode_t			f_mode;  // 文件的访问模式(r模式等)struct mutex		f_pos_lock;loff_t			f_pos; // 读写偏移量struct fown_struct	f_owner; // 所属者信息u64			f_version; // 版本号/* needed for tty driver, and maybe others */void			*private_data;          //隐私数据struct address_space	*f_mapping;} __randomize_layout__attribute__((aligned(4)));	/* lest something weird decides that 2 is OK */

文件结构的函数操作集合:

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 *);......
} __randomize_layout;

2.2 VFS系统调用

‌Linux VFS(虚拟文件系统)包括以下系统调用‌:

‌1. 挂装/卸载文件系统‌:

  • mount():挂装文件系统
  • umount():卸载文件系统
  1. 获取文件系统信息‌:
  • sysfs():获取文件系统信息
  • statfs():获取文件系统的状态信息
  • fstatfs():获取已打开文件的文件系统状态信息
  • ustat():获取统计信息

3.‌ 更改根目录和当前目录‌:

  • chroot():更改根目录
  • chdir():改变当前工作目录
  • fchdir():改变文件描述符的文件目录
  • getcwd():获取当前工作目录的路径

4.‌‌ 创建和删除目录‌:

  • mkdir():创建目录
  • rmdir():删除目录

5.‌‌读取文件状态‌:

  • stat():读取文件状态信息
  • fstat():读取已打开文件的文件状态信息
  • lstat():读取符号链接的状态信息
  • access():检查文件访问权限

6.‌‌‌ 打开/关闭文件‌:

  • open():打开文件
  • close():关闭文件
  • create():创建并打开文件
  • umask():设置文件权限掩码

7.‌‌‌ 对文件描述符进行操作‌:

  • dup():复制文件描述符
  • dup2():复制文件描述符并关闭原描述符
  • fcntl():对文件描述符进行操作

8.‌‌ 异步I/O通告‌:

  • select():异步I/O通告
  • poll():异步I/O通告(较老的接口)

9.‌‌ 进行文件I/O操作‌:

  • read():读取文件内容
  • write():写入文件内容
  • readv():读取多个数据块
  • writev():写入多个数据块
  • sendfile():高效地发送文件内容到套接字或管道中

10.‌‌‌ 对软链接进行操作‌:

  • readlink():读取符号链接的值
  • symlink():创建符号链接

11.‌‌ 更改文件属性‌:

  • chown():更改文件所有者
  • fchown():更改已打开文件的所有者
  • lchown():更改符号链接的所有者
  • chmod():更改文件权限
  • fchmod():更改已打开文件的权限
  • utime():更改文件的访问和修改时间戳

12.‌‌ ‌进行通信操作‌:

  • pipe():创建管道,用于进程间通信‌

3. 文件系统的注册和挂装

内核通过VFS使用一个具体的文件系统之前,必须对这个文件系统进行注册和挂装。
注册文件系统 -> 函数操作 -> 挂装到系统目录

4. 进程与文件系统的联系

5. ext2 文件系统

6. 块设备驱动

7. 字符设备驱动

8. 引用

Linux 文件系统之虚拟文件系统
Linux中的虚拟文件系统(virtual file system)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/460692.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Three.js 快速入门构建你的第一个 3D 应用

![ 开发领域:前端开发 | AI 应用 | Web3D | 元宇宙 技术栈:JavaScript、React、Three.js、WebGL、Go 经验经验:6年 前端开发经验,专注于图形渲染和AI技术 开源项目:github 晓智元宇宙、数字孪生引擎、前端面试题 大家好…

排序算法汇总

一、二分查找 public static int binarySearch(int[] nums,int target){int l 0, r nums.length-1;while(l < r){int mid l (r-l)/2;if(nums[mid] target){return mid;}else if(nums[mid] < target){r mid - 1;}else{l mid 1;}}return -1;} 对于防止溢出的 mid …

类和对象(2)

1.类的默认成员函数 默认成员函数就是⽤⼾没有显式实现&#xff0c;编译器会⾃动⽣成的成员函数称为默认成员函数。⼀个类&#xff0c;我们不写的情况下编译器会默认⽣成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前4个&#xff0c;最后两个取地址重载不…

AcWing 1303:斐波那契前 n 项和 ← 矩阵快速幂加速递推

【题目来源】https://www.acwing.com/problem/content/1305/http://poj.org/problem?id3070【题目描述】 大家都知道 数列吧&#xff0c;。现在问题很简单&#xff0c;输入 和 &#xff0c;求 的前 项和 。【输入格式】 共一行&#xff0c;包含两个整数 和 。【输出格式】…

ElasticSearch备考 -- Index rollover

一、题目 给索引my-index-000001&#xff0c;创建别名my-index&#xff0c;并设置rollover&#xff0c;满足以下三个条件的 The index was created 7 or more days ago.The index contains 5 or more documents.The index’s largest primary shard is 1GB or larger. 二、思考…

zabbix 6.0 监控clickhouse(单机)

zabbix 6.0 LTS已经包含了clickhouse的监控模板&#xff0c;所以我们可以直接使用自带的模板来监控clickhouse了。 0.前置条件 clickhouse 已经安装&#xff0c;我安装的是24.3.5.47zabbix-agent 已经安装并配置。系统是ubuntu 2204 server 1. 新建监控用户 使用xml的方式为…

Jmeter自动化实战

一、前言 由于系统业务流程很复杂,在不同的阶段需要不同的数据,且数据无法重复使用,每次造新的数据特别繁琐,故想着能不能使用jmeter一键造数据 二、创建录制模板 可参考:jmeter录制接口 首先创建一个录制模板 因为会有各种请求头,cookies,签名,认证信息等原因,导致手动复制…

提升网站速度与性能优化的有效策略与实践

内容概要 在数字化快速发展的今天&#xff0c;网站速度与性能优化显得尤为重要&#xff0c;它直接影响用户的浏览体验。用户在访问网站时&#xff0c;往往希望能够迅速获取信息&#xff0c;若加载时间过长&#xff0c;轻易可能导致他们转向其他更为流畅的网站。因此&#xff0…

OpenCV视觉分析之目标跟踪(6)轻量级目标跟踪器类TrackerNano的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 Nano 跟踪器是一个超轻量级的基于深度神经网络&#xff08;DNN&#xff09;的通用目标跟踪器。 由于特殊的模型结构&#xff0c;Nano 跟踪器速度…

C数组手动输入问题

问题界面 解析 输入数组数据也需要加取地址符吗&#xff1f;数组不就是地址了吗&#xff1f; 理解array[i]和array[i][j]的区别&#xff1a; array[i]是一个指向第i行第一个元素的指针&#xff08;int*类型&#xff0c;指向array[i][0]&#xff09;。 array[i][j]是一个int类…

Hadoop-002-部署并配置HDFS集群

集群规划 Hadoop HDFS的角色包含 NameNode(主节点管理者)、DataNode(从节点工作者)、SeconddaryNameNode(从节点辅助) 节点CPU内存hadoop-11C4Ghadoop-21C2Ghadoop-31C2G 一、下载上传Hadoop包 注意: 登录hadoop-1节点root用户执行 1、官网下载安装包后上传 到hadoop-1服务…

Android 在github网站下载项目:各种很慢怎么办?比如gradle下载慢;访问github慢;依赖下载慢

目录 访问github慢gradle下载慢依赖下载慢 前言 大家好&#xff0c;我是前期后期&#xff0c;在网上冲浪的一名程序员。 为什么要看这篇文章呢&#xff1f;问题是什么&#xff1f; 我们在Github上面看到一些好的项目的时候&#xff0c;想下载下来研究学习一下。但经常遇到各…

信息安全数学基础(35)同态和同构

一、同态 定义&#xff1a; 设(M,)和(S,)是两个群&#xff08;或更一般的代数系统&#xff09;&#xff0c;如果存在一个映射σ:M→S&#xff0c;使得对于M中的任意两个元素a、b&#xff0c;都有σ(ab)σ(a)σ(b)&#xff0c;则称σ为M到S的同态或群映射。 性质&#xff1a; 同…

微信小程序中点击搜素按钮没有反应,可能是样式问题(按钮被其他元素覆盖或遮挡)

文章目录 1. 确认 bindtap 绑定在正确的元素上2. 检查是否有遮挡或重叠元素3. 检查 this 上下文绑定问题4. 清除微信小程序开发者工具的缓存5. 用微信开发者工具查看事件绑定6. 确保 handleSearch 没有拼写错误进一步调试 1、searchResults.wxml2、searchResults.wxss3、search…

实验干货|电流型霍尔传感器采样设计03-信号调理

在前两篇博客中&#xff0c;将霍尔输出的电流信号转换成了有正有负的电压信号&#xff0c;但是DSP需要采集0~3V的电压信号&#xff0c;因此需要对信号缩放并抬升至全部为正的信号。 常见的方法是&#xff0c;通过比例放大(缩小)电路对信号进行放缩&#xff0c;通过加法电路抬升…

SQLI LABS | Less-20 POST-Cookie Injections-Uagent field-error based

关注这个靶场的其它相关笔记&#xff1a;SQLI LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;过关流程 输入下面的链接进入靶场&#xff08;如果你的地址和我不一样&#xff0c;按照你本地的环境来&#xff09;&#xff1a; http://localhost/sqli-labs/Less-20/ 可以看到…

爬虫+数据保存2

爬取数据保存到MySQL数据库 这篇文章, 我们来讲解如何将我们爬虫爬取到的数据, 进行保存, 而且是把数据保存到MySQL数据库的方式去保存。 目录 1.使用pymysql连接数据库并执行插入数据sql代码(insert) 2.优化pymysql数据库连接以及插入功能代码 3.爬取双色球网站的数据并保…

echarts 遍历多个图表,并添加resize缩放

数据结构&#xff1a; data() { return { charts: [ { title: Chart 1, xAxisData: [Mon, Tue, Wed, Thu, Fri, Sat, Sun], yAxisData: [120, 200, 150, 80, 70, 110, 130], }, { title: Chart 2, xAxisData: [Jan, Feb, Mar, Apr, May, Jun, Jul], yAxisData: [22…

Linux 中,flock 对文件加锁

在Linux中&#xff0c;flock是一个用于对文件加锁的实用程序&#xff0c;它可以帮助协调多个进程对同一个文件的访问&#xff0c;避免出现数据不一致或冲突等问题。以下是对flock的详细介绍&#xff1a; 基本原理 flock通过在文件上设置锁来控制多个进程对该文件的并发访问。…

(五)Web前端开发进阶2——AJAX

目录 2.Axios库 3.认识URL 4.Axios常用请求方法 5.HTTP协议——请求报文/响应报文 6.前后端分离开发 7.Element组件库 1.Ajax概述 AJAX 是异步的 JavaScript和XML(Asynchronous JavaScript And XML)。简单点说&#xff0c;就是使用XMLHttpRequest 对象与服务器通信。它可…