OJ设计细节 之 【进程资源限制】(getrlimit、setrlimit、prlimit)

目录

[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 SIGSEGVSIGBUS 终止进程 内存分配失败时触发
RLIMIT_DATA SIGSEGVSIGBUS 终止进程 brk()/sbrk() 分配失败
RLIMIT_STACK SIGSEGV 终止进程 栈溢出时触发
RLIMIT_NOFILE 无信号 返回 EMFILE open()/dup() 等返回错误
RLIMIT_NPROC 无信号 返回 EAGAIN fork()/clone() 失败
RLIMIT_FSIZE SIGXFSZ 终止进程 写入超过限制的文件
RLIMIT_CORE 无信号 不生成 core 文件 setrlimitRLIMIT_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);