如何获取 Posix 系统中的总可用磁盘空间?

Posted

技术标签:

【中文标题】如何获取 Posix 系统中的总可用磁盘空间?【英文标题】:How to obtain total available disk space in Posix systems? 【发布时间】:2010-10-10 10:18:48 【问题描述】:

我正在编写一个跨平台应用程序,我需要可用的总磁盘空间。对于 posix 系统(Linux 和 Macos),我使用的是 statvfs。我创建了这个 C++ 方法:

long OSSpecificPosix::getFreeDiskSpace(const char* absoluteFilePath) 
   struct statvfs buf;

   if (!statvfs(absoluteFilePath, &buf)) 
      unsigned long blksize, blocks, freeblks, disk_size, used, free;
      blksize = buf.f_bsize;
      blocks = buf.f_blocks;
      freeblks = buf.f_bfree;

      disk_size = blocks*blksize;
      free = freeblks*blksize;
      used = disk_size - free;

      return free;
   
   else 
      return -1;
   

不幸的是,我得到了一些我无法理解的奇怪值。例如: f_blocks = 73242188 f_bsize = 1048576 f_bfree = 50393643 ...

这些值是以位、字节还是其他形式表示的?我在***上读到这些应该是字节,但是我会得到免费的字节总数: f_bsize*f_bfree = 1048576*50393643 但这意味着 49212.542GB...太多...

我的代码有什么问题吗? 谢谢!

【问题讨论】:

你使用的是什么文件系统,块大小为 1048576? 这是一个 Mac OS 扩展版(区分大小写,日志式)。现在我正在使用 mac,但据我所知,这应该可以工作。 除了你的块大小和你所谓的 70TB 驱动器的怪异之外 - 请注意 32 位 OSX 上的 long 只有 32 位。即使你有正确的数字,这对于你的 blocks 的数量可能已经足够了,但对于你的 bytes 的数量来说还不够大。专业供应商可随时提供 4GB 大的驱动器 ;-) 除了返回类型的错误之外,我没有理由在结构中得到奇怪的值吗?还有其他方法可以获得这些值吗?谢谢! 啊,现在我仔细看看,检查f_bsizef_frsize是否相等。我敢打赌他们不是。块数和空闲块数参考f_frsize,而不是f_bsize 【参考方案1】:

我不太了解 OSX,无法预测这绝对是答案,但 f_blocksf_bfree 实际上指的是“基本块”或“片段”(大小为 buf.f_frsize 字节),不是“文件系统块大小”(即buf.f_bsize 字节):

http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/statvfs.h.html

f_bsize 只是提示 I/O 操作的首选大小,不一定与文件系统的划分方式有关。

【讨论】:

【参考方案2】:

以下几行:

disk_size = blocks*blksize;
free = freeblks*blksize;

拥有 HUGE HD 时会导致溢出。

在我发现我的 HD 为 455GiB 之前,我也得到了奇怪的结果,请考虑在进行乘法之前很久将 blocks、blksize 和 freeblks vars 转换为 unsigned。

类似这样的:

unsigned long long disk_size = (unsigned long long) (blocks) * (unsigned long long) (blksize)

我见过很多这样的问题,但没有人在答案中注意到这一点。

【讨论】:

好收获!我也看到奇怪的数字是(无符号长长)【参考方案3】:

我想最后两个答案是正确且有用的。但是我通过简单地将函数 statvfs 替换为函数 statfs 来解决。块大小是预期的 4096,一切似乎都是正确的。 谢谢!

【讨论】:

我看不到在 OS X 上 statfs 被弃用的地方。statfs 也产生了正确的值。 我也看不到:developer.apple.com/library/mac/#documentation/Darwin/Reference/…. Apple 文档在 statvfs 文档的末尾这样说: statvfs() 和 fstatvfs() 函数符合 IEEE Std 1003.1-2001 (``POSIX.1'')。作为标准化,可移植应用程序根本不能依赖这些函数返回任何有效信息。此实现尝试提供与底层文件系统一样多的有用信息,但受指定数据类型的限制。【参考方案4】:
uint64_t userAvailableFreeSpace()

    struct statvfs stat;
    struct passwd *pw = getpwuid(getuid());
    if ( NULL != pw && 0 == statvfs(pw->pw_dir, &stat) )
    
        uint64_t freeBytes = (uint64_t)stat.f_bavail * stat.f_frsize;
        return freeBytes;
    
    return 0ULL;

【讨论】:

以上是关于如何获取 Posix 系统中的总可用磁盘空间?的主要内容,如果未能解决你的问题,请参考以下文章

Zabbix监控Linux系统所有磁盘的总空间大小脚本

如何在 Postgres 中获取当前的可用磁盘空间?

如何在 Windows 上获取总磁盘大小?

如何在 Bash 中获取当前的可用磁盘空间?

Azure 中如何获取未附加磁盘的磁盘容量和可用空间

如何在 swift 2.0 中使用 AttributesOfFileSystemForpaths 获取总磁盘空间和可用磁盘空间