df和du的区别

df和du的区别

Posted by lwk on January 21, 2020

写这篇文章的目的是:

可能有不少人都了解df和du不一致,可能是有deleted文件但fd还在的问题,但具体df和du是怎么统计磁盘分区大小的呢?你知道吗?

所以写下这篇文章,和大家一起分享下具体逻辑。

从一个简单的示例开始吧,我们使用/data0分区作为整篇文章的实验分区。

写入前,df查看/data0分区avial还有93G可用 image

现在在/data0分区下创建一个大小为1G的文件

image

写入后,df 查看/data0分区avial还有92G可用

image

然后写一个简单的脚本t.py,代码如下,功能只是打开a.log并死循环,每次sleep 10s

#!/usr/bin/env python
import os,sys

if __name__ == "__main__":

   with open("./a.log", "r") as fp:

       while True:

           sleep(10)                 

image 在删除a.log之前我们df和du看下/data0分区的使用情况:

du的结果是已使用8.8G,df结果是已使用9G。

image

接下来删除a.log

image 删除之后,再使用df和du看下/data0的使用情况

image df看到/data0的已使用空间是9G,和第一次df的结果一样;但du查看到/data0分区使用量却只有7.8G,和第一次相比正好少了1G,那1G就是a.log的大小,为什么删除了1G的文件,df统计出来的没有变化,但du的有变化,是什么原因呢?

接下来就带大家一起详细阐述这里的根因。

我一般比较喜欢把源码下载下来编译,然后走GDB,这样更快速的了解源码逻辑。

为了保持和现网版本一致,先查看下现网的使用版本

rpm –qa grep –i coreutils

image

在https://ftp.gnu.com/gun下载对应的coreutils源码进行编译即可

编译成功后,默认在src下生产对应的二进制文件,接下来可进行GDB。

image

image 获取本机文件系统列表 image

有人可能会问/etc/mtab是怎么得到的呢?其实/etc/mtab并不是在coreutils里定义的,而是在glibc里定义的,感兴趣的同学可以把glibc代码拉下来看下。 image

image

image image

image

image

接下来看下du的过程

image

单步走到du_files函数 image

image

image

总结一下:

1、du主要是通过遍历文件,使用fts_read获取每个文件属性信息(包括文件大小、time和RWX属性等),从而计算所占磁盘空间大小

2、df主要是通过文件系统,调用statfs计算所占磁盘空间大小

3、df的statfs会根据文件系统类型调用对应的函数,内核支持的文件系统类型请查看对应版本的内核源码的fs/目录,该目录下列出了支持的文件系统类型。

其实我们lsof可以看到被delete的文件信息,文件已经不存在,但由于fd还在。因此df和du显示结果不一致,相差了正好是a.log的大小,即1G

image