在Linux中每个进程都有一组资源限制,其中一些可以通过下列函数进行查询和更改:

#include <sys/resource.h>
#include <sys/time.h>
int getrlimit(int resource,struct rlimit *rlptr);
int setrlimit(int resource,struct rlimit *rlptr); 

两个函数的返回值:若成功,返回0;若出错,返回-1,并设置相应的errno

其中rlimit结构体为

struct rlimit
{
    rlim_t rlim_cur; //rlim_cur为指定的资源指定当前的系统软限制
    rlim_t rlim_max; //rlim_max为指定的资源指定当前的系统硬限制
};

第一个参数为资源类型

资源限制类型概要描述如下:

  • RLIMIT_CORE

core文件的最大字节数,若其值为0则阻止创建core文件。

  • RLIMIT_CPU

CPU时间的最大量值(秒),当超过此软限制时,向该进程发送S I G X C P U信号。

  • RLIMIT_DATA

一个进程的数据段最大字节长度。数据段中初始化数据、非初始化数据以及堆的总和。当调用函数brk动态改变一个进程的数据段大小时,若失败,errno值将被设置为ENOMEM。

  • RLIMIT_FSIZE

可以创建的文件的最大字节长度。当超过此软限制时,则向该进程发送SIGXFSZ信号。

  • RLIMIT_NOFILE

每个进程能打开的最多文件数。

  • RLIMIT_STACK

栈的最大字节长度。系统不会动态增加栈的大小限制。
在进程内部,setrlimit()将增加限制以适合您的栈大小,而不会移动当前内存段来允许增长。为了保证进程的栈能够增长,限制必须首先改变以适应运行进程使用的新栈大小。
在一个多线程的进程中,若在线程中调用setrlimit(),而该线程不是主线程,则对于栈的限制没有任何改变。使用参数RLIMIT_STACK来调用setrlimit()仅仅能够影响主线程的栈,并且该工作本来就应该由主线程来完成。
当超越栈大小限制时,信号SIGSEGV会发给进程。如果进程忽略该信号,或者捕捉该信号但是没有设置处理措施,该信号默认设置为SIG_DFL处理方案。

  • RLIMIT_VMEM

可映照地址空间的最大字节长度(和RLIMIT_AS相同)。

  • RLIMIT_AS

进程可用内存最大字节数。

- 使用注意

当设置RLIMIT_DATA时,如果被接受,malloc函数可能失败,并设置errno为ENOMEM。

在Linux中,使用mmap()分配的内存不再计入数据段中,而sbrk()和brk()分配的内存才是数据段的一部分。最近的POSIX.1不再指定brk(),许多操作系统也不再将brk()作为系统调用,而是用mmap()替换。最新版的glibc使用mmap()实现malloc内存分配,所以RLIMIT_DATA限制对glibc的malloc函数没有作用。

因此,如果需要限制动态内存分配,设置RLIMIT_AS限制即可。