GETRLIMIT - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-06-09
名称
getrlimit,setrlimit,prlimit-获取/设置资源限制
语法
#包括
#包括
int getrlimit(int resource,struct rlimit * rlim);
int setrlimit(int resource,const struct rlimit * rlim);
int prlimit(pid_t pid,int resource,const struct rlimit * new_limit,
struct rlimit * old_limit);
glibc的功能测试宏要求(请参阅feature_test_macros(7)):
prlimit():_GNU_SOURCE
说明
getrlimit()和setrlimit()系统调用获取和设置资源限制。每个资源都有一个关联的软限制和硬限制,如rlimit结构所定义:
struct rlimit { rlim_t rlim_cur; /* Soft limit */ rlim_t rlim_max; /* Hard limit (ceiling for rlim_cur) */ };
软限制是内核为相应资源强制执行的值。硬限制是软限制的上限:无特权的进程只能将其软限制设置为介于0到硬限制之间的值,并(不可逆地)降低其硬限制。特权进程(在Linux下:初始用户名称空间中具有CAP_SYS_RESOURCE功能的特权进程)可以对两个限制值进行任意更改。
值RLIM_INFINITY表示对资源没有限制(在getrlimit()返回的结构和传递给setrlimit()的结构中)。
resource参数必须是以下之一:
- RLIMIT_AS
- 这是进程的虚拟内存(地址空间)的最大大小。该限制以字节为单位指定,并向下舍入为系统页面大小。此限制影响对brk(2),mmap(2)和mremap(2)的调用,这些调用在超出此限制时会失败,并显示错误ENOMEM。另外,自动堆栈扩展失败(如果没有通过sigaltstack(2)提供备用堆栈,则会生成SIGSEGV,该进程将终止该进程)。由于该值很长,因此在32位长的机器上,此限制最多为2 GB,或者此资源是无限的。
- RLIMIT_CORE
- 这是进程可能转储的核心文件的最大大小(请参阅core(5))。如果为0,则不会创建核心转储文件。当非零时,较大的转储将被截断为此大小。
- RLIMIT_CPU
- 这是对进程可以消耗的CPU时间量的限制(以秒为单位)。当进程达到软限制时,将发送一个SIGXCPU信号。此信号的默认操作是终止进程。但是,可以捕获信号,并且处理程序可以将控制权返回给主程序。如果该进程继续消耗CPU时间,它将每秒发送一次SIGXCPU,直到达到硬限制为止,然后发送SIGKILL。 (后一点描述了Linux的行为。实现方式在处理如何达到达到软限制后仍继续消耗CPU时间的进程方面有所不同。需要捕获此信号的可移植应用程序应在首次收到SIGXCPU时执行有序终止。)
- RLIMIT_DATA
- 这是进程的数据段(初始化数据,未初始化数据和堆)的最大大小。该限制以字节为单位指定,并向下舍入为系统页面大小。此限制影响对brk(2),sbrk(2)和(自Linux 4.7起)mmap(2)的调用,这些调用在遇到此资源的软限制时失败,并显示错误ENOMEM。
- RLIMIT_FSIZE
- 这是该进程可能创建的文件的最大大小(以字节为单位)。尝试将文件扩展到此限制之外会导致SIGXFSZ信号的传递。默认情况下,该信号终止进程,但是进程可以捕获该信号,在这种情况下,相关的系统调用(例如write(2),truncate(2))失败,错误为EFBIG。
- RLIMIT_LOCKS(early Linux 2.4 only)
- 这是此过程可能建立的flock(2)锁和fcntl(2)租约的组合数量的限制。
- RLIMIT_MEMLOCK
- 这是可以锁定到RAM中的最大内存字节数。该限制实际上四舍五入为系统页面大小的最接近倍数。此限制影响mlock(2),mlockall(2)和mmap(2)MAP_LOCKED操作。从Linux 2.6.9开始,它还会影响shmctl(2)SHM_LOCK操作,在此操作上设置共享内存段中的总字节数的最大值(请参见shmget(2)),该字节可能被调用进程的实际用户ID锁定。 shmctl(2)SHM_LOCK锁与mlock(2),mlockall(2)和mmap(2)MAP_LOCKED建立的每个进程的内存锁分开解决;进程可以在这两个类别的每个类别中将字节锁定到此限制。
- 在2.6.9之前的Linux内核中,此限制控制着特权进程可以锁定的内存量。从Linux 2.6.9开始,对特权进程可以锁定的内存量没有任何限制,而是由该限制控制非特权进程可以锁定的内存量。
- RLIMIT_MSGQUEUE(since Linux 2.6.8)
- 这是可以为调用进程的真实用户ID分配给POSIX消息队列的字节数的限制。此限制适用于mq_open(3)。用户创建的每个消息队列都将根据以下公式对这个限制进行计数(直到将其删除):
- 从Linux 3.5开始:
bytes = attr.mq_maxmsg * sizeof(struct msg_msg) + min(attr.mq_maxmsg, MQ_PRIO_MAX) * sizeof(struct posix_msg_tree_node)+ /* For overhead */ attr.mq_maxmsg * attr.mq_msgsize; /* For message data */
- Linux 3.4及更早版本:
bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) + /* For overhead */ attr.mq_maxmsg * attr.mq_msgsize; /* For message data */
- 其中attr是指定为mq_open(3)的第四个参数的mq_attr结构,而msg_msg和posix_msg_tree_node结构是内核内部结构。
- 公式中的"开销"加数说明了实现所需的开销字节,并确保用户不能创建无限数量的零长度消息(尽管如此,每种消息都消耗一些系统内存来记账)。
- RLIMIT_NICE(since Linux 2.6.12, but see BUGS below)
- 这指定了一个上限,可以使用setpriority(2)或nice(2)将进程的nice值提高到该上限。 nice值的实际上限计算为20-rlim_cur。因此,该限制的有用范围是从1(对应于19的良好值)到40(对应于-20的良好值)。范围的这种异常选择是必要的,因为负数不能指定为资源限制值,因为它们通常具有特殊含义。例如,RLIM_INFINITY通常与-1相同。有关nice值的更多详细信息,请参见sched(7)。
- RLIMIT_NOFILE
- 这指定的值比此过程可以打开的最大文件描述符数大一个。尝试(open(2),pipe(2),dup(2)等)超过此限制将产生错误EMFILE。 (从历史上看,此限制在BSD上称为RLIMIT_OFILE。)
- 从Linux 4.5开始,此限制还定义了非特权进程(不具有CAP_SYS_RESOURCE功能的进程)可以通过UNIX域套接字传递给其他进程的最大文件描述符数量。此限制适用于sendmsg(2)系统调用。有关更多详细信息,请参见unix(7)。
- RLIMIT_NPROC
- 这是对调用进程的实际用户ID的现存进程(或更确切地说在Linux中,线程)数量的限制。只要属于该进程的真实用户ID的当前进程数大于或等于此限制,fork(2)就会失败,并显示错误EAGAIN。
- 对于具有CAP_SYS_ADMIN或CAP_SYS_RESOURCE功能的进程,不实施RLIMIT_NPROC限制。
- RLIMIT_RSS
- 这是对进程的驻留集(驻留在RAM中的虚拟页数)的限制(以字节为单位)。此限制仅在Linux 2.4.x,x rlim_cur大于rlim->rlim_max。
- EPERM
- 一个没有特权的过程试图提高硬性限制。为此,需要CAP_SYS_RESOURCE功能。
- EPERM
- 调用方试图将硬RLIMIT_NOFILE限制增加到/ proc / sys / fs / nr_open定义的最大限制(请参阅proc(5))
- EPERM
- (prlimit())调用进程没有权限为pid指定的进程设置限制。
- ESRCH
- 找不到ID为pid中指定的进程。
版本
从Linux 2.6.36开始,可以使用prlimit()系统调用。从glibc 2.13开始提供库支持。
属性
有关本节中使用的术语的说明,请参见attribute(7)。
Interface | Attribute | Value |
getrlimit(),setrlimit(),prlimit() | Thread safety | MT-Safe |
遵循规范
getrlimit(),setrlimit():POSIX.1-2001,POSIX.1-2008,SVr4、4.3BSD。
prlimit():特定于Linux。
RLIMIT_MEMLOCK和RLIMIT_NPROC源自BSD,并且未在POSIX.1中指定;它们出现在BSD和Linux上,但是在其他一些实现上却没有。 RLIMIT_RSS源自BSD,并且未在POSIX.1中指定;但是,它在大多数实现中都存在。 RLIMIT_MSGQUEUE,RLIMIT_NICE,RLIMIT_RTPRIO,RLIMIT_RTTIME和RLIMIT_SIGPENDING特定于Linux。
备注
通过fork(2)创建的子进程继承其父级的资源限制。资源限制在execve(2)中保留。
资源限制是进程中所有线程共享的每个进程属性。
将资源的软限制降低到该进程当前对该资源的消耗以下将会成功(但将阻止该进程进一步增加其对资源的消耗)。
可以使用内置的ulimit命令(csh(1)中的limit)设置外壳的资源限制。 Shell的资源限制由其创建以执行命令的进程继承。
从Linux 2.6.24开始,可以通过/ proc / [pid] / limits检查任何进程的资源限制;参见proc(5)。
古代系统提供的vlimit()函数的用途与setrlimit()相似。为了向后兼容,glibc还提供了vlimit()。所有新应用程序都应使用setrlimit()编写。
C library/kernel ABI differences
从版本2.13开始,出于BUGS中所述的原因,glibc getrlimit()和setrlimit()包装函数不再调用相应的系统调用,而是使用prlimit()。
glibc包装函数的名称是prlimit();。底层系统调用是prlimit64()。
BUGS
在较旧的Linux内核中,当进程遇到软性和硬性RLIMIT_CPU限制时,将传递SIGXCPU和SIGKILL信号,其发送时间应比原应晚一秒。此问题已在内核2.6.8中修复。
在2.6.17之前的2.6.x内核中,RLIMIT_CPU限制为0被错误地视为"无限制"(例如RLIM_INFINITY)。从Linux 2.6.17开始,将限制设置为0确实有效,但实际上被视为1秒的限制。
内核错误意味着RLIMIT_RTPRIO在2.6.12内核中不起作用;该问题已在内核2.6.13中修复。
在内核2.6.12中,getpriority(2)和RLIMIT_NICE返回的优先级范围之间存在不一的不匹配。这样的结果是尼斯值的实际上限被计算为19-rlim_cur。此问题已在内核2.6.13中修复。
从Linux 2.6.12开始,如果进程达到其软RLIMIT_CPU限制并为SIGXCPU安装了处理程序,则除了调用信号处理程序外,内核还会将软限制增加一秒钟。如果该进程继续消耗CPU时间,直到达到硬限制,然后终止该进程,此行为就会重复。其他实现不以这种方式更改RLIMIT_CPU软限制,并且Linux行为可能不符合标准。可移植的应用程序应避免依赖于此特定于Linux的行为。遇到软限制时,特定于Linux的RLIMIT_RTTIME限制表现出相同的行为。
当rlim-> rlim_cur大于rlim-> rlim_max时,2.4.22之前的内核无法诊断setrlimit()的错误EINVAL。
由于兼容性原因,当尝试设置RLIMIT_CPU失败时,Linux不会返回错误。
Representation of large resource limit values on 32-bit platforms
即使在32位平台上,glibc getrlimit()和setrlimit()包装函数也使用64位rlim_t数据类型。但是,在系统调用getrlimit()和setrlimit()中使用的rlim_t数据类型为(32位)无符号长。此外,在Linux中,内核将32位平台上的资源限制表示为无符号长。但是,32位数据类型不够宽。这里最相关的限制是RLIMIT_FSIZE,它指定文件可以增长到的最大大小:为了有用,此限制必须使用与表示文件偏移量的类型一样宽的类型来表示-即,与64位off_t一样宽(假定使用_FILE_OFFSET_BITS = 64编译的程序)。
要解决此内核限制,如果程序试图将资源限制设置为大于32位无符号长表示的值,则glibc setrlimit()包装函数会将限制值静默转换为RLIM_INFINITY。换句话说,所请求的资源限制设置被静默忽略。
从2.13版开始,glibc通过实现setrlimit()和getrlimit()作为调用prlimit()的包装函数,来解决getrlimit()和setrlimit()系统调用的限制。
示例
下面的程序演示了prlimit()的用法。
#define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 #include <stdio.h> #include <time.h> #include <stdlib.h> #include <unistd.h> #include <sys/resource.h> #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ } while (0) int main(int argc, char *argv[]) { struct rlimit old, new; struct rlimit *newp; pid_t pid; if (!(argc == 2 || argc == 4)) { fprintf(stderr, "Usage: %s <pid> [<new-soft-limit> " "<new-hard-limit>]\n", argv[0]); exit(EXIT_FAILURE); } pid = atoi(argv[1]); /* PID of target process */ newp = NULL; if (argc == 4) { new.rlim_cur = atoi(argv[2]); new.rlim_max = atoi(argv[3]); newp = &new; } /* Set CPU time limit of target process; retrieve and display previous limit */ if (prlimit(pid, RLIMIT_CPU, newp, &old) == -1) errExit("prlimit-1"); printf("Previous limits: soft=%lld; hard=%lld\n", (long long) old.rlim_cur, (long long) old.rlim_max); /* Retrieve and display new CPU time limit */ if (prlimit(pid, RLIMIT_CPU, NULL, &old) == -1) errExit("prlimit-2"); printf("New limits: soft=%lld; hard=%lld\n", (long long) old.rlim_cur, (long long) old.rlim_max); exit(EXIT_SUCCESS); }
另外参见
prlimit(1),dup(2),fcntl(2),fork(2),getrusage(2),mlock(2),mmap(2),open(2),quotactl(2),sbrk(2), shmctl(2),malloc(3),sigqueue(3),ulimit(3),core(5),功能(7),cgroups(7),凭据(7),signal(7)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。