首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有nftw的目录的总大小与du输出不同。

具有nftw的目录的总大小与du输出不同。
EN

Stack Overflow用户
提问于 2013-09-21 18:51:44
回答 1查看 1.2K关注 0票数 0

我已经编写了一小部分代码,它使用nftw系统调用来执行树遍历。

代码语言:javascript
复制
int flags =0;
flags = flags | FTW_MOUNT;
int nopenfd = 10;

if( nftw( argv[1], sum_sizes, nopenfd, flags) == -1 )
  return EXIT_FAILURE;

有了这些选项,nftw就不会扫描目录,如果它是一个挂载点和取消引用符号链接(默认行为)。

在每个文件中,nftw调用此函数:

代码语言:javascript
复制
/*total_size is the sum of each file/directory/link*/
long long int total_size, total_real_size = 0;

static int sum_sizes(const char *pathname, const struct stat *statbuf, int typeflag, struct FTW *ftwbuf)
{
/*if stat failed on the current file*/
if(typeflag == FTW_NS)
{
    printf("No stats (permissions ?) on %s", pathname);
    return 0;
}
total_size = total_size + (long long int ) statbuf->st_size;
total_real_size = total_real_size + (long long int ) ( statbuf->st_blocks * 512 );
return 0;
}

最后,我显示了累积大小:

代码语言:javascript
复制
printf("total size: %lld (%0.2lf K %0.2lf M)\n", total_size,  (float)total_size /1024.0, (float)total_size /(1024.0*1024.0));
printf("total real size: %lld (%0.2lf K %0.2lf M)\n", total_real_size,  (float)total_real_size /1024.0, (float)total_real_size /(1024.0*1024.0));

当我将值与du进行比较时,我有一些不同之处

代码语言:javascript
复制
time ./scan_dir ~/        
====>
total size: 15208413390 (14851966.00 K 14503.87 M)
total real size: 15708553216 (15340384.00 K 14980.84 M)
block size : 4096 / fond. block size : 4096
fs size: 22.7895 G
./scan_dir ~/  0,03s user 0,24s system 98% cpu 0,277 total


time du -s ~/     
15119876    /home/cedlemo/
du -s ~/  0,07s user 0,22s system 98% cpu 0,287 total

注意:在阅读了du的手册页后,我知道du的行为与我的小应用程序scan_dir几乎相同(跳过挂载点、删除符号链接并使用1024来计算is在Ko中的值)。

在我的应用程序中找到的更接近的值似乎是实际大小的总和(所使用的块),但是值并不完全相同。

造成这种差异的原因是什么?我做错什么了?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-09-22 00:02:08

默认情况下,du不遵循符号链接。你的密码有。

代码语言:javascript
复制
du -ks DIRECTORY/

等于

代码语言:javascript
复制
find DIRECTORY/ -printf '%k\n' | awk '{s+=$1} END { printf "%.0f\n", s }'

它只查看每个目录条目一次,不遵循符号链接,不交叉挂载点,并输出st_blocks*2的总和(即1024字节单位)。换句话说,分配给文件和目录内容的1024字节单元的数量--磁盘使用情况.

另一方面,逻辑文件和目录大小之和是

代码语言:javascript
复制
find DIRECTORY/ -printf '%s\n' | awk '{s+=$1} END { printf "%.0f\n", s / 1024.0 }'

这与磁盘的使用无关,只涉及存储在文件和目录中的信息的明显数量。通常,此度量仅限于常规文件,即

代码语言:javascript
复制
find DIRECTORY/ -type f -printf '%s\n' | awk '{s+=$1} END { printf "%.0f\n", s / 1024.0 }'

因此,它基本上告诉用户,如果他们将所有的文件连接到一个巨大的文件中,他们会得到多大的文件。它是否有意义是值得商榷的,但许多用户认为它提供了信息。无论如何,这肯定是一个与磁盘使用不同的度量方法。

在文件统计信息(请参阅man 2 fstat)中,st_blocks描述了为文件内容分配了多少个512个字节的单元,并对文件的逻辑大小进行了st_size

大多数文件系统支持稀疏文件。这意味着当您使用truncate()放大文件时,或者通过写入比当前文件大小更高的文件偏移量,文件系统根本不会存储跳过的部分。然而,读这部分是完全没有问题的;它将永远读为全零。因此,一个巨大的文件可能只消耗几个块,如果它主要是零。(准确地说,是“跳过零”。在创建文件时,只写零并不会产生稀疏文件。您的应用程序需要跳过编写零,以生成稀疏文件。)

由于某些文件系统上的某些文件使用的间接块,块的数量也有可能大于基于文件大小的假定。可能有“额外的块”分配和考虑,因为文件是支离破碎的或其他特殊的。在所有典型的文件系统上,所分配的块的数量无论如何都是文件系统分配大小的倍数。

在您的示例中,如果要将所有文件和目录的内容连接到一个文件中,包括符号链接所引用的任何副本,则total size是文件的逻辑长度。

在您的示例中,如果将符号链接替换为原始文件的副本,则total real size描述为所有文件和目录分配的磁盘空间总量。

如果你改变到

代码语言:javascript
复制
flags = FTW_MOUNT | FTW_PHYS;

您应该得到与total real size匹配的du -s

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18936326

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档