getrlimit、setrlimit

进程资源限制详解
本文介绍了如何使用getrlimit和setrlimit来查询和修改进程的资源限制,并详细解释了rlimit结构及其各种资源限制参数的意义。同时,文章还提供了如何通过示例代码来展示系统当前的软限制和硬限制。

每个进程都有一组资源的限制,通过getrlimit、setrlimit能查寻和改变资源限制。

getrlimit, setrlimit, prlimit - get/set resource limits

#include <sys/time.h>
#include <sys/resource.h>

int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);

//Return: 0 if OK, nonzero on error

系统资源限制是系统启动时由进程0设置的,且由后续的进程继承。
其中特殊的结构rlimit如下:

struct rlimit {
               rlim_t rlim_cur;  /* Soft limit */
               rlim_t rlim_max;  /* Hard limit (ceiling for rlim_cur) */
};

改变资源限制的三个准则

  • 进程的软限制(soft limit)需要小于等于硬限制(hard limit)
  • 进程可以降低其硬限制,以大于等于soft limit。注意:降低硬限制对一般用户不可逆!
  • 仅仅超级用户进程(superuser process)可以提高硬限制

常量RLIM_INFINITY表示无限的限制
resource使用如下图的参数(Linux 3.2.0):

Resource
RLIMIT_ASThe maximum size in bytes of a process’s total available memory. This affects the sbrk function (Section 1.11) and the mmap function (Section 14.8).
RLIMIT_COREThe maximum size in bytes of a core file. A limit of 0 prevents the creation of a core file.
RLIMIT_CPUThe maximum amount of CPU time in seconds. When the soft limit is exceeded, the SIGXCPU signal is sent to the process.
RLIMIT_DATAThe maximum size in bytes of the data segment: the sum of the initialized data, uninitialized data, and heap from Figure 7.6.
RLIMIT_FSIZEThe maximum size in bytes of a file that may be created. When the soft limit is exceeded, the process is sent the SIGXFSZ signal.
RLIMIT_MEMLOCKThe maximum amount of memory in bytes that a process can lock into memory using mlock(2).
RLIMIT_MSGQUEUEThe maximum amount of memory in bytes that a process can allocate for POSIX message queues.
RLIMIT_NICEThe limit to which a process’s nice value (Section 8.16) can be raised to affect its scheduling priority.
RLIMIT_NOFILEThe maximum number of open files per process. Changing this limit affects the value returned by the sysconf function for its _SC_OPEN_MAX argument (Section 2.5.4). See Figure 2.17 also.
RLIMIT_NPROCThe maximum number of child processes per real user ID. Changing this limit affects the value returned for _SC_CHILD_MAX by the sysconf function (Section 2.5.4).
RLIMIT_RSSMaximum resident set size (RSS) in bytes. If available physical memory is low, the kernel takes memory from processes that exceed their RSS.
RLIMIT_SIGPENDINGThe maximum number of signals that can be queued for a process. This limit is enforced by the sigqueue function (Section 10.20).
RLIMIT_STACKThe maximum size in bytes of the stack. See Figure 7.6.
  • shelllimit command:set or report file size limit

Example:

打印出系统当前的soft limithard limit

#include <sys/resource.h>
#define doit(name) pr_limit(#name, name)
static void pr_time(char *name, int resource)
{
    struct rlimit limit;
    if(getrlimit(resource, &limit) < 0)//获取资源
        出错处理;
    printf("%s ", name);
    if(limit.rlim_cur == RLIM_INFINITY)//查看当前的soft limit
        printf("(infinity)");
    else
        printf("%d\n", limit.rlim_cur);
    if(limit.rlim_max == RLIM_INFINITY)//查看硬限制hard limit
        printf("(infinity)");
    else
        printf("%d\n", limit.rlim_max);
}

使用doit(RLIMIT_CORE);
等效于pr_limit("RLIMIT_CORE", RLIMIT_CORE);

<think>我们讨论的是在Linux环境下使用getrlimitsetrlimit系统调用来获取和设置资源限制,特别是栈资源限制(如设置为12MB)以及CPU资源限制。这些函数允许我们查询和修改进程的资源限制。 ### 1. 基本概念 - `getrlimit` 和 `setrlimit` 是用于获取和设置进程资源限制的系统调用。 - 每个资源都有两个限制值:当前软限制(soft limit)和最大硬限制(hard limit)。 - 软限制是内核实际执行的限制,进程可以将其增加到最大硬限制值。非特权进程只能降低硬限制,不能提高硬限制。 - 资源类型通过`resource`参数指定,常见的资源类型有: - `RLIMIT_STACK`:进程栈的最大大小(单位:字节)。如果超过这个限制,将收到`SIGSEGV`信号。 - `RLIMIT_CPU`:进程使用CPU的最大时间(单位:秒)。如果超过,将收到`SIGXCPU`信号。 ### 2. 函数原型 ```c #include <sys/resource.h> int getrlimit(int resource, struct rlimit *rlim); int setrlimit(int resource, const struct rlimit *rlim); ``` 其中,`struct rlimit`定义如下: ```c struct rlimit { rlim_t rlim_cur; /* 当前软限制 */ rlim_t rlim_max; /* 最大硬限制 */ }; ``` ### 3. 设置栈资源限制为12MB 栈资源限制由`RLIMIT_STACK`指定。12MB等于12 * 1024 * 1024字节。 示例代码: ```c #include <sys/resource.h> #include <stdio.h> #include <stdlib.h> int main() { struct rlimit rlim; // 获取当前的栈限制 if (getrlimit(RLIMIT_STACK, &rlim) == -1) { perror("getrlimit"); exit(1); } printf("当前栈限制: soft = %ld, hard = %ld (字节)\n", (long)rlim.rlim_cur, (long)rlim.rlim_max); // 设置新的栈限制:软限制为12MB,硬限制不变(保持原硬限制) rlim_t new_stack_size = 12 * 1024 * 1024; // 12MB if (new_stack_size > rlim.rlim_max) { // 如果新限制大于硬限制,且我们有权限,可以尝试提高硬限制 // 但非特权进程通常不能提高硬限制 printf("新限制超过硬限制,无法设置\n"); exit(1); } rlim.rlim_cur = new_stack_size; if (setrlimit(RLIMIT_STACK, &rlim) == -1) { perror("setrlimit"); exit(1); } printf("已设置栈软限制为 %ld 字节\n", (long)new_stack_size); return 0; } ``` ### 4. 获取CPU资源限额 CPU资源限制由`RLIMIT_CPU`指定,单位是秒。 示例代码(获取CPU限制): ```c #include <sys/resource.h> #include <stdio.h> #include <stdlib.h> int main() { struct rlimit rlim; if (getrlimit(RLIMIT_CPU, &rlim) == -1) { perror("getrlimit"); exit(1); } printf("CPU时间限制: soft = %ld 秒, hard = %ld 秒\n", (long)rlim.rlim_cur, (long)rlim.rlim_max); return 0; } ``` ### 5. 设置CPU资源限制 设置CPU资源限制与设置栈限制类似,但注意单位是秒。 ```c // 设置CPU软限制为60秒(1分钟),硬限制保持原样 rlim_t new_cpu_limit = 60; if (getrlimit(RLIMIT_CPU, &rlim) == -1) { perror("getrlimit"); exit(1); } // 保存原来的硬限制 rlim_t old_hard = rlim.rlim_max; // 设置软限制 rlim.rlim_cur = new_cpu_limit; // 如果新的软限制大于硬限制,且我们需要调整硬限制,则先调整硬限制(但非特权进程可能无法提高硬限制) // 这里我们不改变硬限制,所以确保软限制不超过硬限制 if (rlim.rlim_cur > rlim.rlim_max) { // 如果新软限制大于硬限制,且进程有权限,可以尝试提高硬限制 // 但通常非特权进程不能提高硬限制,所以这里我们只将软限制设置为硬限制的值 rlim.rlim_cur = rlim.rlim_max; } if (setrlimit(RLIMIT_CPU, &rlim) == -1) { perror("setrlimit"); exit(1); } ``` ### 6. 注意事项 - 非特权进程(非root)只能将硬限制降低,不能提高。也就是说,如果当前硬限制是X,那么软限制可以设置为0到X之间的值,而硬限制只能降低(且降低后不能提高)。 - 设置资源限制可能会影响进程的行为,例如设置栈大小过小可能导致栈溢出。 - 设置CPU限制后,当进程使用的CPU时间超过软限制时,系统会向进程发送`SIGXCPU`信号,默认行为是终止进程。但进程可以捕获这个信号并做清理工作。 ### 7. 完整示例:设置栈限制和获取CPU限制 ```c #include <sys/resource.h> #include <stdio.h> #include <stdlib.h> int main() { struct rlimit rlim; // 设置栈限制为12MB rlim_t new_stack = 12 * 1024 * 1024; if (getrlimit(RLIMIT_STACK, &rlim) == -1) { perror("getrlimit stack"); exit(1); } if (new_stack <= rlim.rlim_max) { rlim.rlim_cur = new_stack; if (setrlimit(RLIMIT_STACK, &rlim) == -1) { perror("setrlimit stack"); } else { printf("栈限制设置成功:%ld 字节\n", (long)new_stack); } } else { printf("无法设置栈限制:请求大小超过硬限制\n"); } // 获取CPU限制 if (getrlimit(RLIMIT_CPU, &rlim) == -1) { perror("getrlimit cpu"); } else { printf("CPU时间限制:软限制=%ld秒,硬限制=%ld秒\n", (long)rlim.rlim_cur, (long)rlim.rlim_max); } return 0; } ``` ### 8. 编译和运行 使用gcc编译: ```bash gcc rlimit_example.c -o rlimit_example ./rlimit_example ``` ### 相关问题 1. 如何设置进程的最大文件描述符数量? 2. 如何获取和设置进程的数据段大小(例如堆内存)? 3. 资源限制在进程间是如何继承的? 4. 如何通过shell命令(ulimit)设置栈和CPU限制? 5. 在守护进程中设置资源限制的最佳实践是什么?</think>### 使用 getrlimitsetrlimit 管理资源限制 在 Linux 系统中,`getrlimit` 和 `setrlimit` 系统调用用于获取和设置进程的资源限制。以下是获取/设置栈资源限制(如 12MB)和 CPU 资源限额的详细方法: #### 1. 资源限制结构体 ```c #include <sys/resource.h> struct rlimit { rlim_t rlim_cur; // 当前软限制(实际生效值) rlim_t rlim_max; // 最大硬限制(不可超过的值) }; ``` #### 2. 获取和设置栈资源限制(12MB) ```c #include <sys/resource.h> #include <stdio.h> int main() { struct rlimit rlim; // 获取当前栈限制 if (getrlimit(RLIMIT_STACK, &rlim) == -1) { perror("getrlimit failed"); return 1; } printf("当前栈限制: soft=%ldMB, hard=%ldMB\n", rlim.rlim_cur/(1024*1024), rlim.rlim_max/(1024*1024)); // 设置新栈限制为12MB rlim.rlim_cur = 12 * 1024 * 1024; // 12MB if (setrlimit(RLIMIT_STACK, &rlim) == -1) { perror("setrlimit failed"); return 1; } printf("已设置栈限制为12MB\n"); return 0; } ``` #### 3. 获取 CPU 资源限额 ```c #include <sys/resource.h> #include <stdio.h> int main() { struct rlimit rlim; // 获取CPU时间限制 if (getrlimit(RLIMIT_CPU, &rlim) == -1) { perror("getrlimit failed"); return 1; } if (rlim.rlim_cur == RLIM_INFINITY) { printf("CPU时间限制: 无限制\n"); } else { printf("CPU时间限制: %ld秒\n", rlim.rlim_cur); } return 0; } ``` #### 4. 关键参数说明 | 资源类型 | 宏定义 | 单位 | 说明 | |-------------------|-------------------|------------|-------------------------------| | 栈大小 | `RLIMIT_STACK` | 字节 | 进程栈的最大尺寸 | | CPU时间 | `RLIMIT_CPU` | 秒 | 进程可使用的CPU时间 | | 虚拟内存 | `RLIMIT_AS` | 字节 | 进程地址空间总大小 | | 文件大小 | `RLIMIT_FSIZE` | 字节 | 可创建文件的最大尺寸 | #### 5. 重要注意事项 1. **权限要求**: - 非特权进程只能降低硬限制,不能提高 - 只有特权进程(root)可以提高硬限制 2. **特殊值**: - `RLIM_INFINITY` 表示无限制 - 栈限制最小值通常为 128KB-256KB 3. **错误处理**: - 函数返回 -1 表示失败,检查 `errno`: - `EPERM`: 权限不足 - `EINVAL`: 无效参数 - `EFAULT`: 地址错误 4. **栈限制实际效果**: $$ \text{实际栈大小} = \min(\text{RLIMIT\_STACK}, \text{编译时指定的栈大小}) $$ 程序链接时可通过 `-z stack-size` 指定栈大小[^1] #### 6. 编译和执行 ```bash # 编译 gcc resource_limit.c -o rlimit_test # 执行 ./rlimit_test ``` #### 7. 系统级监控 查看当前进程限制: ```bash cat /proc/$$/limits # $$ 表示当前shell进程ID ``` 示例输出: ``` Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max stack size 8192 unlimited bytes ``` ### 相关问题 1. 如何设置进程的最大内存使用量? 2. 资源限制在子进程中是如何继承的? 3. 如何通过编程方式获取当前进程的资源使用统计? 4. `RLIMIT_NPROC` 和 `RLIMIT_NOFILE` 分别控制什么资源? 5. 在守护进程中设置资源限制的最佳实践是什么? 6. 如何避免因资源限制导致的程序崩溃? [^1]: Linux 手册页 `man 2 getrlimit` [^2]: 《UNIX环境高级编程》第7章 进程环境
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值