C++ 如何在Posix系统中获得总可用磁盘空间?
我正在编写一个跨平台的应用程序,我需要总的可用磁盘空间。对于posix系统(Linux和Macos),我使用的是statvfs。我创建了这个C++方法:C++ 如何在Posix系统中获得总可用磁盘空间?,c++,linux,macos,unix,posix,C++,Linux,Macos,Unix,Posix,我正在编写一个跨平台的应用程序,我需要总的可用磁盘空间。对于posix系统(Linux和Macos),我使用的是statvfs。我创建了这个C++方法: long OSSpecificPosix::getFreeDiskSpace(const char* absoluteFilePath) { struct statvfs buf; if (!statvfs(absoluteFilePath, &buf)) { unsigned long blksize, bl
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_块=73242188
f_bsize=1048576
f_bfree=50393643
这些值是以位、字节或其他形式表示的吗?我在stackoverflow上读到这些应该是字节,但是我会得到空闲字节的总数是:
f_bsize*f_bfree=1048576*50393643
但这意味着49212.542GB。。。太多了
我是否在代码或其他方面出错?
谢谢 我对OSX的了解不足以预测这肯定是答案,但
f_block
和f_bfree
实际上指的是“基本块”或“片段”(大小buf.f_frsize
字节),而不是“文件系统块大小”(即buf.f_bsize
字节):
f_bsize
只是提示I/O操作的首选大小,它不一定与文件系统的划分方式有关。我认为最后两个答案是正确和有用的。但是,我通过简单地用函数statfs替换函数statfs解决了这个问题。块大小如预期的那样为4096,并且一切似乎都是正确的。
谢谢 以下几行:
disk_size = blocks*blksize;
free = freeblks*blksize;
当有巨大的HDs时会导致溢出
<>我也得到了奇怪的结果,直到我知道我的HD是445 GIB,在做乘法之前,请考虑铸造块、BLKSIZE和FLUBLKS VARS到无符号长。
大概是这样的:
unsigned long long disk_size = (unsigned long long) (blocks) * (unsigned long long) (blksize)
我见过很多这样的问题,但没有人在答案中注意到这一点。您使用的文件系统的块大小为1048576?这是一个Mac OS扩展文件系统(区分大小写,有日志记录)。现在我正在mac上工作,但据我所知,这应该是可行的。除了块大小和据称的70TB驱动器的奇怪之处之外,请注意,32位OSX上的
长只有32位。即使有了正确的数字,也可能足够大,可以容纳块的数量,但不能容纳字节的数量。专业供应商随时提供4GB大小的驱动器;-)除了返回类型上的错误,没有理由在结构中得到奇怪的值吗?还有其他方法获得这些值吗?谢谢啊,现在我仔细看看,看看f_bsize
和f_frsize
是否相等。我打赌他们不是。块和空闲块的数量指的是f\u frsize
,而不是f\u bsize
。我看不出在OS X上哪里不推荐使用statfs
。另外statfs
生成正确的值。我也看不到:。苹果文档在statfs文档的末尾说了这一点:statfs()和fstatvfs()功能符合IEEE标准1003.1-2001(“POSIX.1”)。按照标准,便携式应用程序根本不能依赖这些函数返回任何有效信息。此实现试图提供底层文件系统提供的尽可能多的有用信息,但受指定数据类型的限制。很好!我也看到了奇怪的数字(无符号长)
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;
}