我们来学习一下 quotactl 这个系统调用。它主要用于管理 Linux 系统上的磁盘配额,帮助系统管理员控制用户或组可以使用的磁盘空间量 。
1. 函数介绍 quotactl 是一个 Linux 系统调用(System Call),它提供了一个底层接口来操作 Unix 和 Linux 操作系统中的磁盘配额 。简单来说,它允许你设置和查询特定用户(UID)或组(GID)在某个文件系统上可以使用的磁盘空间上限 。这对于防止某个用户或组占用过多磁盘资源,确保系统资源公平分配非常有用。
2. 函数原型 1 2 3 4 #include <sys/quota.h> int quotactl(int cmd, const char *special, int id, caddr_t addr);
3. 功能 这个函数的主要功能是操作磁盘配额 。根据传入的 cmd 参数,它可以执行多种操作,比如设置配额限制、获取当前配额使用情况、开启或关闭文件系统的配额检查等 。
4. 参数
cmd: int 类型。这是一个命令参数,指定了要执行的具体操作以及配额的类型(用户配额或组配额) 。通常使用 QCMD(subcmd, type) 宏来构造这个命令。subcmd 是具体的操作(如 Q_QUOTAON, Q_QUOTAOFF, Q_GETQUOTA, Q_SETQUOTA 等),type 是配额类型(通常是 USRQUOTA 表示用户配额,GRPQUOTA 表示组配额) 。
special: const char * 类型。指向一个以 null 结尾的字符串,该字符串表示要操作的文件系统设备的路径名(例如 “/dev/sda1”)或挂载点(例如 “/home”) 。
id: int 类型。指定要操作的用户 ID (UID) 或组 ID (GID),具体取决于 cmd 中指定的类型 。
addr: caddr_t 类型(通常可以看作 void *)。一个地址指针,指向包含操作所需数据的缓冲区,或者用于存放函数返回的数据。具体指向的数据结构取决于 cmd 指定的操作 。例如,如果是获取配额信息 (Q_GETQUOTA),它指向一个 struct dqblk 结构体变量,函数会将结果填入其中;如果是设置配额信息 (Q_SETQUOTA),它指向一个包含新配额设置的 struct dqblk 结构体变量。
5. 返回值
6. 相似函数或关联函数
quota 命令: 这是一个用户空间的命令行工具,用于显示用户或组的磁盘配额信息。它内部可能会使用 quotactl 系统调用来获取信息。
quotacheck 命令: 用于扫描文件系统并创建或更新配额文件(如 aquota.user 和 aquota.group),这些文件存储了配额信息 。
edquota 命令: 用于编辑用户或组的磁盘配额限制,它也依赖于 quotactl 来应用更改。
QCMD 宏: 用于构造 quotactl 的 cmd 参数 。
struct dqblk: 这是与 quotactl 配合使用的一个重要结构体,用于存储或传递配额限制和使用情况的数据。
7. 示例代码 前提: 运行这些示例代码需要 root 权限,因为管理配额是系统管理员的任务。同时,目标文件系统需要支持并已启用配额功能。
data-ad-format="fluid"
data-ad-layout-key="-7k+ex-4a-9w+4a">
示例 1: 获取用户磁盘配额信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <stdio.h> #include <unistd.h> #include <sys/quota.h> #include <errno.h> #include <string.h> int main() { // 假设我们要查询 /home 文件系统的用户配额 const char *mount_point = "/home"; // 假设我们要查询 UID 为 1001 的用户的配额 int user_id = 1001; struct dqblk quota_info; int result; // 使用 QCMD 宏构造 cmd 参数:操作是 Q_GETQUOTA,类型是 USRQUOTA (用户配额) result = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), mount_point, user_id, (caddr_t)"a_info); if (result == -1) { perror("quotactl"); // 打印错误信息 fprintf(stderr, "Failed to get quota info for user %d on %s\n", user_id, mount_point); return 1; } // 打印获取到的配额信息 // 注意: 数值通常以 1KB 块为单位 printf("User ID: %d\n", user_id); printf("Block Hard Limit: %llu KB\n", (unsigned long long)quota_info.dqb_bhardlimit); printf("Block Soft Limit: %llu KB\n", (unsigned long long)quota_info.dqb_bsoftlimit); printf("Current Blocks Used: %llu KB\n", (unsigned long long)quota_info.dqb_curblocks); printf("Inode Hard Limit: %llu\n", (unsigned long long)quota_info.dqb_ihardlimit); printf("Inode Soft Limit: %llu\n", (unsigned long long)quota_info.dqb_isoftlimit); printf("Current Inodes Used: %llu\n", (unsigned long long)quota_info.dqb_curinodes); // dqb_btime 和 dqb_itime 是宽限时间,当超过软限制时才相关 // printf("Block Grace Time Expiry: %lu\n", quota_info.dqb_btime); // printf("Inode Grace Time Expiry: %lu\n", quota_info.dqb_itime); return 0; }
示例 2: 设置用户磁盘配额限制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 #include <stdio.h> #include <unistd.h> #include <sys/quota.h> #include <errno.h> #include <string.h> #include <time.h> // 需要设置宽限时间 int main() { // 假设我们要设置 /home 文件系统的用户配额 const char *mount_point = "/home"; // 假设我们要设置 UID 为 1002 的用户的配额 int user_id = 1002; struct dqblk new_quota_limits; int result; // 初始化结构体 memset(&new_quota_limits, 0, sizeof(new_quota_limits)); // 设置块(磁盘空间)限制 (单位通常是 1KB 块) new_quota_limits.dqb_bhardlimit = 500000; // 硬限制 500MB new_quota_limits.dqb_bsoftlimit = 400000; // 软限制 400MB // 设置 inode(文件数量)限制 new_quota_limits.dqb_ihardlimit = 5000; // 硬限制 5000 个文件 new_quota_limits.dqb_isoftlimit = 4000; // 软限制 4000 个文件 // 设置宽限时间 (秒) - 当超过软限制时,用户还有这段时间可以清理,之后硬限制生效 // 如果不设置或设置为0,可能会使用默认值或导致软限制行为异常 new_quota_limits.dqb_btime = time(NULL) + 7 * 24 * 60 * 60; // 7天后 new_quota_limits.dqb_itime = time(NULL) + 7 * 24 * 60 * 60; // 7天后 // 设置有效的字段标志,告诉内核我们要设置哪些字段 new_quota_limits.dqb_valid = QIF_LIMITS | QIF_TIMES; // 设置限制和时间 // 使用 QCMD 宏构造 cmd 参数:操作是 Q_SETQUOTA,类型是 USRQUOTA (用户配额) result = quotactl(QCMD(Q_SETQUOTA, USRQUOTA), mount_point, user_id, (caddr_t)&new_quota_limits); if (result == -1) { perror("quotactl"); // 打印错误信息 fprintf(stderr, "Failed to set quota limits for user %d on %s\n", user_id, mount_point); return 1; } printf("Successfully set quota limits for user %d on %s\n", user_id, mount_point); printf("Block Hard Limit: %llu KB, Soft Limit: %llu KB\n", (unsigned long long)new_quota_limits.dqb_bhardlimit, (unsigned long long)new_quota_limits.dqb_bsoftlimit); printf("Inode Hard Limit: %llu, Soft Limit: %llu\n", (unsigned long long)new_quota_limits.dqb_ihardlimit, (unsigned long long)new_quota_limits.dqb_isoftlimit); return 0; }
编译和运行:
1 2 3 4 5 6 7 8 9 10 # 假设代码保存在 get_quota.c 和 set_quota.c 中 # 需要 root 权限编译和运行 sudo gcc -o get_quota get_quota.c sudo gcc -o set_quota set_quota.c # 运行前确保 /home 文件系统启用了用户配额 # 运行示例 (需要 root 权限) sudo ./get_quota sudo ./set_quota
请注意,实际使用中需要确保文件系统已经正确配置并启用了配额功能,这通常涉及在 /etc/fstab 中添加 usrquota 或 grpquota 选项,并使用 quotacheck 和 quotaon 命令初始化和启用配额。
quotactl 系统调用, quotactl 命令详解, linux quotactl 用法, quotactl 示例代码, linux 系统调用 quotactl, quotactl 函数说明, linux 磁盘配额管理, 系统调用 quotactl 解析, quotactl 实战教程, linux quotactl 教程
相关文章:
quotactl系统调用及示例-CSDN博客
quotactl(2) - Linux manual page
https://www.calcguide.tech/2025/08/28/quotactl系统调用及示例/