百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

「干货」从 lsof 开始,深入理解 Linux 虚拟文件系统

nanshan 2024-11-10 10:13 25 浏览 0 评论



背景


有时会出现这样的情况,磁盘空间显示已经被占满,但是在查看磁盘的具体文件占用情况时,发现磁盘仍然有很大的空余空间。


1. 执行df命令查看磁盘使用情况,发现磁盘已经满了。

-bash-4.2$ df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda1 ext4 30G 30G 0 100% /
devtmpfs devtmpfs 489M 0 489M 0% /dev
tmpfs tmpfs 497M 0 497M 0% /dev/shm
tmpfs tmpfs 497M 50M 447M 11% /run
tmpfs tmpfs 497M 0 497M 0% /sys/fs/cgroup


2. 执行du命令查看各个目录的磁盘占用情况,把各个目录文件的大小相加,发现并没有占满磁盘,有10多G空间莫名失踪。

-bash-4.2$ du -h --max-depth=1 /home
16M /home/logs
11G /home/serverdog
11G /home


3. 为何会出现这样的情况呢?

因为虽然文件已被删除,但是一些进程仍然打开这些文件,因此其占用的磁盘空间并没有被释放。执行lsof命令显示打开已删除的文件。将有问题的进程重启(或,清空),磁盘空间就会得到释放。

-bash-4.2# lsof | grep delete
mysqld 2470 mysql 4u REG 253,1 0 523577 /var/tmp/ibfTeQFn (deleted)
mysqld 2470 mysql 5u REG 253,1 0 523579 /var/tmp/ibaHcIdW (deleted)
mysqld 2470 mysql 6u REG 253,1 0 523581 /var/tmp/ibLjiALu (deleted)
mysqld 2470 mysql 7u REG 253,1 0 523585 /var/tmp/ibCFnzTB (deleted)
mysqld 2470 mysql 11u REG 253,1 0 523587 /var/tmp/ibCjuqva (deleted)


那么,Linux的文件系统,到底为什么这么设计呢?要了解这些,就要先弄清楚并不容易,下面将从一些基本概念入手,一步步将这些梳理清楚:


虚拟文件系统
(virtaul filesystem)


下图显示了Linux操作系统中负责文件管理的基本组件。上半区域为用户模式,下半区域为内核模式。应用程序使用标准库libc来访问文件,库将请求映射到系统调用,以便进入内核模式。


所有与文件相关的操作的入口都是虚拟文件系统(VFS),而非特定的额文件系统(如Ext3、ReiserFS和NFS)。VFS 提供了系统库和特定文件系统之间的接口。因此,VFS 不仅充当抽象层,而且实际上它提供了一个文件系统的基本实现,可以由不同的实现来使用和扩展。因此,要了解文件系统是如何工作的,就要先了解VFS 。


通用文件模型

VFS 的主要思想在于引入了一个通用文件模型(common file model)。通用文件模型由以下对象类型组成:


  • 超级块对象(superblock object)

内存:文件系统安装时创建,存放文件系统的有关信息
磁盘:对应于存放在磁盘上的文件系统控制块(filesystem control block)

  • 索引节点对象(inode object)

内存:访问时创建,存放关于具体文件的一般信息(inode 结构)
磁盘:对应于存放在磁盘上的文件控制块(file control block)
每个索引节点对象都有一个索引节点号,唯一地标识文件系统的文件

  • 文件对象(file object)

内存:打开文件时创建,存放打开文件与进程之间进行交互的有关信息(file 结构)
打开文件信息,仅当进程访问文件期间存在于内核内存中。

  • 目录项对象(dentry object)

内存:目录项一旦被读入内存,VFS就会将其转换成dentry 结构的目录项对象
磁盘:特定文件系统以特定的方式存储在磁盘上
存放目录项(即,文件名称)与对应文件进行链接的有关信息


目录树

综合来说,Linux 的 根文件系统(system's root filessystem) 是内核启动mount的第一个文件系统。内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后,从中把一些基本的初始化脚本和服务等加载到内存中去运行(文件系统和内核是完全独立的两个部分)。其他文件系统,则后续通过脚本或命令作为子文件系统安装在已安装文件系统的目录上,最终形成整个目录树。

start_kernel
  vfs_caches_init
    mnt_init
      init_rootfs // 注册rootfs文件系统
      init_mount_tree // 挂载rootfs文件系统
  …
  rest_init
  kernel_thread(kernel_init, NULL, CLONE_FS);


就单个文件系统而言,在文件系统安装时,创建超级块对象;沿树查找文件时,总是首先从初识目录的中查找匹配的目录项,以便获取相应的索引节点,然后读取索引节点的目录文件,转化为dentry对象,再检查匹配的目录项,反复执行以上过程,直至找到对应的文件的索引节点,并创建索引节点对象。


软链接 vs 硬链接

软链接是一个普通的文件,其中存放的是另外一个文件的路径名。硬链接则指向同一个索引节点,硬链接数记录在索引节点对象的i_nlink字段。当i_nlink字段为零时,说明没有硬链接指向该文件。






文件 & 进程管理


下图是一个简单示例,说明进程是怎样与文件进行交互。三个不同进程打开同一个文件,每个进程都有自己的文件对象,其中两个进程使用同一个硬链接(每个硬链接对应一个目录对象),两个目录项对象都指向同一个 索引节点对象。


索引节点的数据又由两部分组成:内存数据和磁盘数据。Linux 使用Write back作为索引节点的数据一致性策略。对于索引节点的数据,当文件被打开时,才会加载索引节点到内存;当不再被进程使用,则从内存踢出;如果中间有更新,则需要把数据写回磁盘。

* "in_use" - valid inode, i_count > 0, i_nlink > 0
* "dirty" - as "in_use" but also dirty
* "unused" - valid inode, i_count = 0


索引节点是否仍在使用,是通过open()和close()操作建立和销毁文件对象,文件对象通过索引节点提供的iget和iput更新索引节点的i_count字段,以完成使用计数。open 操作使得 i_count 加一, close 操作使得 i_count 减一。在 close 操作时判断索引节点是否释放,如果 i_count = 0,则意味着不再有进程引用,将会从内存释放。






文件 & 磁盘管理


文件与磁盘管理联系最紧密的操作,莫过于touch和rm操作,而尤以后者最为关键。通过strace(或 dtruss),查看rm的实际的系统调用。

# dtruss rm tmp
...
geteuid(0x0, 0x0, 0x0) = 0 0
ioctl(0x0, 0x4004667A, 0x7FFEE06F09C4) = 0 0
lstat64("tmp\0", 0x7FFEE06F0968, 0x0) = 0 0
access("tmp\0", 0x2, 0x0) = 0 0
unlink("tmp\0", 0x0, 0x0) = 0 0


可以发现rm实际是通过unlink完成的。unlink代表删除目录项,以及减少其索引节点的计数。由通用文件模型可知,父目录本身同样是一个文件,也就意味着目录项是其文件数据的一部分。删除目录项等价于从父目录的文件中删除数据,也就意味着首先要打开父目录的文件。那么,删除操作即可理解为:


1、删除命令(一个进程)使用open操作获得父目录文件对象

2、通过iget增加 目录文件的索引节点对象计数
3、读取目录文件数据

  • 将目录文件数据转化为目录项对象

  • 由于目录项包含文件的索引节点,类似的,需要通过iget增加文件的索引节点对象计数

4、删除目录的目录项
5、减少文件索引节点对象的硬链接计数i_nlink
6、通过iput结束对文件索引节点对象的操作,使用计数i_count减一

  • 判断i_count是否为零,如果为零,则释放内存

  • 然后,判断i_nlink是否为零,如果为零,则释放磁盘空间

7、通过iput结束对目录索引节点对象的操作。






总结


回头来看遇到的问题,其实可以从两个角度来理解:


索引与数据

文件系统与文件、磁盘管理与文件、进程管理与文件,最核心的都是文件的索引,而不是文件的数据。把数据和索引分开是理解文件系统的关键。

一个数据构建了各式各样的索引,只有索引全部失效,此时数据才失去意义,此时才能释放


缓存策略

由于操作系统使用 Write back 的策略,意味着只有先释放内存,才有可能释放磁盘。


Why lsof ?

从上面的模型可以很清楚的理解,因为目录已经没有索引到文件了,但是打开文件还有索引到文件,所以不能立刻释放磁盘空间。


为什么 lsof 可以找到已删除未释放的文件呢?

lsof,顾名思义:list open files,该命令的原理就是查找打开文件的列表,因此可以找到已删除未释放的文件。

相关推荐

如何为MySQL服务器和客户机启用SSL?

用户想要与MySQL服务器建立一条安全连接时,常常依赖VPN隧道或SSH隧道。不过,获得MySQL连接的另一个办法是,启用MySQL服务器上的SSL封装器(SSLwrapper)。这每一种方法各有其...

Mysql5.7 出现大量 unauthenticated user

线上环境mysql5.7突然出现大量unauthenticateduser,进mysql,showprocesslist;解决办法有:在/etc/hosts中添加客户端ip,如192.16...

MySQL 在 Windows 系统下的安装(mysql安装教程windows)

更多技术文章MySQL在Windows系统下的安装1.下载mysql和Framework链接链接:百度网盘请输入提取码提取码:6w3p双击mysql-installer-communit...

MySql5.7.21.zip绿色版安装(mysql数据库绿色版安装)

1、去网上下载满足系统要求的版本(mysql-5.7.21-winx64.zip)2、直接解压3、mysql的初始化(1)以管理员身份运行cmd,在mysql中的bin目录下shift+右键-在...

MySQL(8.0)中文全文检索 (亲测有效)

在一堆文字中找到含有关键字的应用。当然也可以用以下语句实现:SELECT*FROM<表名>WHERE<字段名>like‘%ABC%’但是它的效率太低,是全盘扫描。...

新手教程,Linux系统下MySQL的安装

看了两三个教程。终于在哔哩哔哩找到一个简单高效的教程,成功安装,up主名叫bili逍遥bili,感兴趣可以去看看。下面这个是我总结的安装方法环境:CentOS764位1.下载安装包,个人觉得在...

麒麟服务器操作系统安装 MySQL 8 实战指南

原文连接:「链接」Hello,大家好啊,今天给大家带来一篇麒麟服务器操作系统上安装MySQL8的文章,欢迎大家分享点赞,点个在看和关注吧!MySQL作为主流开源数据库之一,被广泛应用于各种业务...

用Python玩转MySQL的全攻略,从环境搭建到项目实战全解析

这是一篇关于“MySQL数据库入门实战-Python版”的教程,结合了案例实战分析,帮助初学者快速掌握如何使用Python操作MySQL数据库。一、环境准备1.安装Python访问Pytho...

安装MySQL(中标麒麟 安装mysql)

安装MySQL注意:一定要用root用户操作如下步骤;先卸载MySQL再安装1.安装包准备(1)查看MySQL是否安装rpm-qa|grepmysql(2)如果安装了MySQL,就先卸载rpm-...

Mysql最全笔记,快速入门,干货满满,爆肝

目录一、MySQL的重要性二、MySQL介绍三、软件的服务架构四、MySQL的安装五、SQL语句六、数据库相关(DDL)七、表相关八、DML相关(表中数据)九、DQL(重点)十、数据完...

MAC电脑安装MySQL操作步骤(mac安装mysqldb)

1、在官网下载MySQL:https://dev.mysql.com/downloads/mysql/根据自己的macOS版本,选择适配的MySQL版本根据自己需求选择相应的安装包,我这里选择macO...

mysql主从(mysql主从切换)

1、本章面试题什么是mysql主从,主从有什么好处什么是读写分离,有什么好处,使用mycat如何实现2、知识点2.1、课程回顾dubboORM->MVC->RPC->SOApro...

【linux学习】以MySQL为例,带你了解数据库

做运维的小伙伴在日常工作中难免需要接触到数据库,不管是MySQL,mariadb,达梦还是瀚高等其实命令都差不多,下面我就以MySQL为例带大家一起来了解下数据库。有兴趣的小伙伴不妨评论区一起交流下...

玩玩WordPress - 环境简介(0)(玩玩网络科技有限公司)

简介提到开源博客系统,一般都会直接想到WordPress!WordPress是使用PHP开发的,数据库使用的是MySQL,一般会在Linux上运行,Nginx作为前端。这时候就需要有一套LNMP(Li...

服务器常用端口都有哪些?(服务器端使用的端口号范围)

下面为大家介绍一下,服务器常用的一些默认端口,以及他们的作用:  21:FTP服务所开放的端口,用于上传、下载文件。  22:SSH端口,用于通过命令行模式远程连接Linux服务器或vps。  23:...

取消回复欢迎 发表评论: