Linux/macOS 下用 statvfs 获取 /tmp 所在文件系统总/可用空间最可靠,需用 f_frsize × f_blocks 和 f_frsize × f_bavail 计算,而非 f_bsize 或 f_bfree;Windows 下须先用 GetVolumePathName 提取 TEMP 目录所在卷根,再调用 GetDiskFreeSpaceEx。

Linux/macOS 下用 statfs 查临时目录所在文件系统的总/可用空间
临时目录(如 /tmp)本身没有“大小”概念,它只是挂载点上的一个路径;真正可查的是它所在的文件系统容量。直接对 /tmp 调用 statvfs 或 statfs 就行,不用先解析符号链接或判断是否独立挂载——只要路径存在且可访问,系统就能返回其底层文件系统的统计信息。
推荐用 POSIX 标准的 statvfs,兼容性更好:
#include <sys/statvfs.h>
#include <iostream>
<p>int main() {
struct statvfs buf;
if (statvfs("/tmp", &buf) == 0) {
auto total = static_cast<uint64_t>(buf.f_frsize) <em> buf.f_blocks;
auto free = static_cast<uint64_t>(buf.f_frsize) </em> buf.f_bfree;
std::cout << "Total: " << total << " bytes\n";
std::cout << "Free: " << free << " bytes\n";
}
}
-
f_frsize是“基本块大小”,不是f_bsize(I/O 块大小),计算总空间必须用它 - 如果程序以非 root 权限运行,
/tmp可能受 userquota 或 project quota 限制,statvfs返回的是文件系统级数据,不反映配额限制 - 某些容器环境(如 Docker)中
/tmp是 tmpfs,f_blocks表示内存页上限,但实际可用可能受 cgroup memory limit 约束,需额外检查/sys/fs/cgroup/memory/memory.limit_in_bytes
Windows 下用 GetDiskFreeSpaceEx 获取 TEMP 目录所在卷的剩余空间
Windows 没有统一的“临时目录文件系统视图”,得先用 GetTempPath 获取路径,再用 GetVolumePathName 提取卷根(比如把 C:\Users\A\AppData\Local\Temp 归到 C:\),最后调用 GetDiskFreeSpaceEx。
关键点是不能直接传 GetTempPath 结果给 GetDiskFreeSpaceEx——它只接受卷根路径(末尾带反斜杠):
立即学习“C++免费学习笔记(深入)”;
#include <windows.h>
#include <iostream>
<p>int main() {
wchar_t tempPath[MAX_PATH];
if (GetTempPath(MAX_PATH, tempPath)) {
wchar_t volumeRoot[MAX_PATH];
if (GetVolumePathName(tempPath, volumeRoot, MAX_PATH)) {
ULARGE_INTEGER free, total, avail;
if (GetDiskFreeSpaceEx(volumeRoot, &free, &total, &avail)) {
std::wcout << L"Free: " << free.QuadPart << L" bytes\n";
}
}
}
}
- 务必用宽字符版本(
GetTempPathW、GetVolumePathNameW),否则在含 Unicode 路径时可能截断或失败 -
GetDiskFreeSpaceEx返回的free是“所有用户可用空间”,而avail是“当前用户可用空间”(受磁盘配额影响),一般应优先看avail - 如果程序运行在 Windows Sandbox 或某些精简版系统中,
TEMP可能指向 RAM disk(如%SystemRoot%\Temp映射到内存),此时数值反映的是虚拟内存分配上限,而非物理磁盘空间
跨平台封装时注意 std::filesystem::temp_directory_path() 的陷阱
C++17 的 std::filesystem::temp_directory_path() 看起来很理想,但它只返回路径字符串,不保证该路径存在、可写,也不说明它是否跨文件系统。更麻烦的是:它可能返回空、抛异常,或返回一个软链接指向别处(比如 macOS 上 /var/folders/... 实际是 /private/var/folders/...)。
- 调用前必须用
std::filesystem::exists()和std::filesystem::is_directory()校验,否则statvfs或GetDiskFreeSpaceEx可能失败 - Linux 下若
/tmp是符号链接(如指向/run/user/1000/tmp),statvfs仍应传原始路径(/tmp),系统会自动解析;不要自己read_symlink后再传目标路径,否则可能误判为另一文件系统 - 在构建系统(如 CMake)中启用
-std=c++17且链接-lstdc++fs(GCC)或确保 MSVC 版本 ≥ 19.20,否则std::filesystem功能不可用
为什么不能用 du -sh /tmp 这类命令替代?
执行 shell 命令看似简单,但实际问题很多:权限限制(普通用户无法读取其他用户在 /tmp 创建的目录)、竞态(命令执行瞬间和你后续操作之间空间可能已被占满)、解析开销(要 fork + exec + pipe + 字符串解析),还引入了对 /bin/sh 和外部工具的依赖。
- 尤其在嵌入式或容器场景中,镜像可能不含
du,或/tmp是 noexec 挂载,导致system()直接失败 - 即使成功,
du统计的是当前已用空间,而你真正关心的是“还能写多少”,这必须靠文件系统级接口(statvfs/GetDiskFreeSpaceEx)获取剩余配额 - 若真要用命令,至少用
find /tmp -xdev -type f -printf "%s\n" 2>/dev/null | awk '{sum += $1} END {print sum+0}'避免跨文件系统,但仍不解决根本问题
临时目录的“大小”本质是运行时上下文问题:它取决于挂载选项、配额策略、cgroup 限制、甚至 SELinux 策略。硬编码路径或依赖外部工具只会让逻辑更脆弱。最稳的方式,是始终基于实际使用的路径做 statvfs 或等价系统调用,并准备好 fallback 路径(比如 /tmp 不可用时尝试 PWD 所在目录)。


















