如何获取 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_bsize
和f_frsize
是否相等。我敢打赌他们不是。块数和空闲块数参考f_frsize
,而不是f_bsize
。
【参考方案1】:
我不太了解 OSX,无法预测这绝对是答案,但 f_blocks
和 f_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 系统中的总可用磁盘空间?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 swift 2.0 中使用 AttributesOfFileSystemForpaths 获取总磁盘空间和可用磁盘空间