目录
[1.struct rlimit](#1.struct rlimit)
[软限制 vs 硬限制](#软限制 vs 硬限制)
[2. getrlimit() - 获取资源限制](#2. getrlimit() - 获取资源限制)
[3. setrlimit() - 设置资源限制](#3. setrlimit() - 设置资源限制)
[4. prlimit() - 进程资源限制查询/设置(扩展版)](#4. prlimit() - 进程资源限制查询/设置(扩展版))

各大OJ平台都会对用户提交的算法进行资源限制,下面详解进程资源限制接口
1.struct rlimit
#include <sys/resource.h>
struct rlimit {
rlim_t rlim_cur; /* 软限制 (soft limit) */
rlim_t rlim_max; /* 硬限制 (hard limit) */
};
| 成员 | 类型 | 说明 | 作用 |
|---|---|---|---|
rlim_cur |
rlim_t |
软限制 | 系统实际强制执行的限制值,进程可主动降低但通常不能提高 |
rlim_max |
rlim_t |
硬限制 | 软限制的上限值,只有特权进程才能提高 |
-
rlim_t 类型
/* 通常定义为 unsigned long 或 unsigned long long /
typedef unsigned long rlim_t; / 64位系统 */ -
取值范围:0 到 RLIM_INFINITY(通常为 -1UL 即 0xFFFFFFFFFFFFFFFF)
-
RLIM_INFINITY 表示无限制
软限制 vs 硬限制
| 特性 | 软限制 (rlim_cur) | 硬限制 (rlim_max) |
|---|---|---|
| 当前生效值 | 是 | 仅作为上限 |
| 进程可修改范围 | 0 到 rlim_max |
只能降低(普通进程)或任意修改(root) |
| 非特权进程 | 可降低 | 只能降低到 ≥ 软限制 |
| 特权进程 (root) | 可任意设置 | 可任意设置 |
| 超限后果 | 触发限制行为 | 无直接作用 |
| 典型用途 | 实际约束进程 | 防止进程无限提高软限制 |
特殊值
| 宏 | 值 | 含义 |
|---|---|---|
RLIM_INFINITY |
-1UL (0xFFFFFFFFFFFFFFFF) |
无限制 |
不同资源类型的典型限制值
| resource | 典型软限制 | 典型硬限制 | 单位 | 说明 | 典型用途 |
|---|---|---|---|---|---|
RLIMIT_CPU |
无限 | 无限 | 秒 | CPU 时间限制 | 防止死循环耗尽 CPU |
RLIMIT_AS |
无限 | 无限 | 字节 | 进程总虚拟内存 | 防止内存泄漏 |
RLIMIT_DATA |
无限 | 无限 | 字节 | 数据段+堆内存 | 限制动态内存分配 |
RLIMIT_STACK |
8 MB | 无限 | 字节 | 栈空间大小 | 防止栈溢出 |
RLIMIT_NOFILE |
1024 | 4096 | 个数 | 打开文件描述符数 | 防止文件描述符泄漏 |
RLIMIT_NPROC |
无限 | 无限 | 个数 | 进程/线程数 | 防止 fork 炸弹 |
RLIMIT_FSIZE |
无限 | 无限 | 字节 | 创建文件的最大大小 | 限制输出文件大小 |
RLIMIT_CORE |
0 | 无限 | 字节 | core dump 文件大小 | 控制调试信息(0=禁用) |
RLIMIT_MEMLOCK |
64 KB | 64 KB | 字节 | 锁定内存大小 | 限制 mlock()/mlockall() |
RLIMIT_SIGPENDING |
无限 | 无限 | 个数 | 挂起信号队列长度 | 限制信号队列堆积 |
RLIMIT_MSGQUEUE |
无限 | 无限 | 字节 | POSIX 消息队列大小 | 限制 IPC 消息队列 |
RLIMIT_NICE |
0 | 0 | - | nice 值限制 | 限制进程优先级调整范围 |
RLIMIT_RTPRIO |
0 | 0 | - | 实时优先级限制 | 限制实时进程优先级 |
RLIMIT_RTTIME |
无限 | 无限 | 微秒 | 实时任务 CPU 时间 | 限制实时任务执行时间 |
- 在 Linux 下,RLIMIT_NPROC 限制的是每个真实用户 ID(UID)的进程和线程总数
资源限制信号表
| resource | 超限时的信号 | 默认行为 | 说明 |
|---|---|---|---|
RLIMIT_CPU |
SIGXCPU |
终止进程 | 超过软限制后每秒发送一次,达到硬限制时发送 SIGKILL |
RLIMIT_AS |
SIGSEGV 或 SIGBUS |
终止进程 | 内存分配失败时触发 |
RLIMIT_DATA |
SIGSEGV 或 SIGBUS |
终止进程 | brk()/sbrk() 分配失败 |
RLIMIT_STACK |
SIGSEGV |
终止进程 | 栈溢出时触发 |
RLIMIT_NOFILE |
无信号 | 返回 EMFILE |
open()/dup() 等返回错误 |
RLIMIT_NPROC |
无信号 | 返回 EAGAIN |
fork()/clone() 失败 |
RLIMIT_FSIZE |
SIGXFSZ |
终止进程 | 写入超过限制的文件 |
RLIMIT_CORE |
无信号 | 不生成 core 文件 | setrlimit 后 RLIMIT_CORE=0 禁用 core dump |
RLIMIT_MEMLOCK |
无信号 | 返回 ENOMEM |
mlock()/mlockall() 失败 |
RLIMIT_SIGPENDING |
无信号 | 返回 EAGAIN |
sigpending() 队列满 |
RLIMIT_MSGQUEUE |
无信号 | 返回 EAGAIN |
mq_send() 失败 |
RLIMIT_NICE |
无信号 | 返回 EPERM |
nice()/setpriority() 失败 |
RLIMIT_RTPRIO |
无信号 | 返回 EPERM |
sched_setscheduler() 失败 |
RLIMIT_RTTIME |
SIGXCPU |
终止进程 | 超过限制后收到 SIGXCPU |
常用限制值参考
| 场景 | RLIMIT_CPU | RLIMIT_AS | RLIMIT_STACK | RLIMIT_NOFILE |
|---|---|---|---|---|
| 在线判题系统 | 1-10 秒 | 256-512 MB | 64-128 MB | 100-200 |
| Web 服务器 | 无限 | 无限 | 8 MB | 65535 |
| 编译任务 | 无限 | 1-2 GB | 无限 | 4096 |
| 后台服务 | 无限 | 无限 | 8 MB | 1048576 |
| Shell 环境 | 无限 | 无限 | 8 MB | 1024 |
查看和设置命令
# 查看所有限制
ulimit -a
# 查看单项
ulimit -t # CPU time (seconds)
ulimit -v # virtual memory (KB)
ulimit -s # stack size (KB)
ulimit -n # open files
ulimit -u # processes
ulimit -c # core dump size (blocks)
# 设置限制
ulimit -t 10 # CPU 时间限制 10 秒
ulimit -v 524288 # 虚拟内存限制 512 MB
ulimit -n 2048 # 文件描述符限制 2048
2. getrlimit() - 获取资源限制
| 项目 | 说明 |
|---|---|
| 函数原型 | int getrlimit(int resource, struct rlimit *rlim); |
| 功能 | 获取指定资源的当前软限制和硬限制 |
| 参数 resource | 资源类型(见上表) |
| 参数 rlim | 输出参数,返回限制值 |
| 返回值 | 成功返回 0,失败返回 -1 |
| 错误码 | EFAULT:rlim 指针无效 EINVAL:resource 无效 EPERM:权限不足 |
| 结构体定义 | struct rlimit { rlim_t rlim_cur; // 软限制 rlim_t rlim_max; // 硬限制}; |
| 使用示例 | struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { printf("软限制: %lu, 硬限制: %lu\n", rl.rlim_cur, rl.rlim_max);} |
3. setrlimit() - 设置资源限制
| 项目 | 说明 |
|---|---|
| 函数原型 | int setrlimit(int resource, const struct rlimit *rlim); |
| 功能 | 设置指定资源的软限制和硬限制 |
| 参数 resource | 资源类型(见上表) |
| 参数 rlim | 输入参数,指定新的限制值 |
| 返回值 | 成功返回 0,失败返回 -1 |
| 错误码 | EFAULT:rlim 指针无效 EINVAL:resource 无效或限制值无效 EPERM:无权提高硬限制 ESRCH:进程不存在(仅限 prlimit) |
| 重要规则 | ① 普通进程只能降低硬限制 ② 软限制 ≤ 硬限制 ③ 子进程继承父进程限制 ④ root 可任意设置 |
| 使用示例 | struct rlimit rl; rl.rlim_cur = 1024; // 软限制 rl.rlim_max = 2048; // 硬限制 if (setrlimit(RLIMIT_NOFILE, &rl) == -1) { perror("setrlimit failed");} |
4. prlimit() - 进程资源限制查询/设置
| 项目 | 说明 |
|---|---|
| 函数原型 | int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlimit *old_limit); |
| 功能 | 查询或设置任意进程的资源限制(Linux 特有) |
| 参数 pid | 目标进程 PID: • 0:调用进程自身 • >0:指定进程 • -1:未定义(不可用) |
| 参数 resource | 资源类型(见上表) |
| 参数 new_limit | 新限制(设置为 NULL 表示仅查询) |
| 参数 old_limit | 旧限制(若不为 NULL,返回原值) |
| 返回值 | 成功返回 0,失败返回 -1 |
| 权限要求 | ① 同用户:可查询和降低限制 ② root:可任意修改 ③ 需要 CAP_SYS_RESOURCE 能力 |
| 优势 | ① 原子操作(查询+设置) ② 可操作其他进程 ③ 避免竞态条件 |
| 使用示例 | // 仅查询其他进程 struct rlimit old; prlimit(target_pid, RLIMIT_AS, NULL, &old);// 设置并获取旧值(原子操作) struct rlimit new = {1024*1024, 1024*1024}; struct rlimit old; prlimit(0, RLIMIT_AS, &new, &old); |