推荐优先使用 statvfs 获取文件系统块大小(f_bsize 为 I/O 推荐粒度,f_frsize 为实际分配单元),总容量应为 f_blocks * f_frsize;配额信息必须通过 quotactl 系统调用获取,且仅 Linux 原生支持,跨平台需降级处理。

Linux 下用 statfs 或 statvfs 读取块大小和配额元数据
直接调用系统 API 是最可靠的方式,statvfs 更现代、POSIX 标准,推荐优先用;statfs 在某些嵌入式或旧内核环境可能更兼容。两者都返回包含 f_bsize(文件系统 I/O 块大小)、f_frsize(底层分配单元大小)的关键字段——注意,f_bsize 不等于磁盘物理扇区,它反映的是文件系统推荐的读写粒度,而 f_frsize 才更接近实际分配块大小。
常见错误是把 f_blocks * f_bsize 当作总空间,其实应使用 f_blocks * f_frsize 计算总容量,否则在 XFS 或 Btrfs 等支持可变块大小的文件系统上会严重偏差。
示例片段:
#include <sys/statvfs.h>
struct statvfs buf;
if (statvfs("/home", &buf) == 0) {
printf("I/O block size: %ld\n", buf.f_bsize); // 推荐读写单位
printf("Fragment size: %ld\n", buf.f_frsize); // 实际分配粒度
printf("Total bytes: %ld\n", buf.f_blocks * buf.f_frsize);
printf("Free bytes: %ld\n", buf.f_bfree * buf.f_frsize);
}获取用户/组配额需调用 quotactl,不是 stat 系列能覆盖的
statvfs 只给整体文件系统视图,不包含 per-user 或 per-group 配额信息。要查某用户的磁盘配额(如 soft/hard limits、当前用量),必须用 Linux 特有的 quotactl 系统调用,配合 QCMD 宏构造命令,并传入 struct dqblk 缓冲区。
立即学习“C++免费学习笔记(深入)”;
容易踩的坑:
- 目标文件系统必须已启用配额(
mount时带usrquota或grpquota选项) - 程序需有
CAP_SYS_ADMIN权限,或以 root 运行;普通用户调用会直接返回-1并设errno = EPERM -
quotactl的第四个参数(data 指针)不能为nullptr,即使只查状态也得传合法地址
简例(查 UID=1000 的用户配额):
#include <linux/quota.h>
#include <sys/quota.h>
struct dqblk dq;
if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), "/dev/sda2", 1000, (caddr_t)&dq) == 0) {
printf("Used: %lld KB, Soft: %lld KB, Hard: %lld KB\n",
dq.dqb_curspace / 1024,
dq.dqb_bsoftlimit / 1024,
dq.dqb_bhardlimit / 1024);
}跨平台不可行:Windows/macOS 没有等效的 quotactl 或统一配额接口
C++ 标准库完全不提供配额或底层块大小支持;Boost.Filesystem 也仅封装路径与基础属性(如大小、时间),不触达文件系统级元数据。Linux 是唯一能通过标准系统调用拿到完整配额+块大小组合信息的主流平台。
Windows 上可通过 GetDiskFreeSpaceEx 获取簇大小(类似 f_frsize)和剩余空间,但无用户配额 API(除非走 WMI 或第三方工具如 fsutil);macOS 的 statfs 能读块大小,但配额需依赖 repquota 外部命令解析输出——这意味着你得 popen("repquota -u username") 并手工 parse 文本,稳定性差、权限要求高、且不保证格式一致。
所以,若项目需跨平台配额统计,实际方案往往是:Linux 用 quotactl + statvfs,其他平台降级为只报告总/可用空间,明确文档注明“配额信息仅 Linux 支持”。
不要依赖 df 命令输出做自动化解析
虽然 df -B1 --output=source,fstype,used,avail,pcent,target 看起来方便,但它的输出格式受 locale、列宽、挂载点含空格或特殊字符等影响极大。例如 df 在中文 locale 下可能把 “Use%” 显示为 “已用%”,字段顺序也可能因版本变动(如 coreutils 9.0+ 新增了 --output,旧版只能靠 awk 切空格,一遇 NFS 挂载点含空格就崩)。
真正健壮的做法是绕过 shell,直接调用 statvfs 和 quotactl;若必须用命令,至少用 df --output=json(coreutils ≥ 9.2),再由 JSON 解析器处理——但依然比系统调用多一层失败可能(如 df 被 PATH 劫持、磁盘满导致 df 自身失败)。
另外,df 默认显示的是“非 root 用户可见剩余空间”,即已扣除 root reserved blocks(通常 5%),而 statvfs 的 f_bfree 是纯剩余块数,f_bavail 才对应 df 的 “Avail” 列。这点在监控阈值告警时极易出错。


















