当前位置:嗨网首页>书籍在线阅读

25-限制项

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

6.7.1 限制项

当前,Linux提供了16种资源限制:

RLIMIT_AS

限制了进程地址空间上限值,单位是字节。如果要增加的地址空间大小超过该上限值——比如调用mmap()和brk()函数,这些调用会失败,返回ENOMEM。如果进程的栈自动增加,超过了限制,内核会给进程发送SIGSEGV信号。该限制的值通常为RLIM_INFINITY。

RLIMIT_CORE

core文件大小的最大值,单位是字节。如果该上限值非0,超出限制的core文件将截短为最大限制大小;如果是0,则不会生成core文件。

RLIMIT_CPU

一个进程可以使用的最长CPU时间,单位是秒。如果进程运行的时间超出这个限制,内核会发出SIGXCPU信号,进程会接收并处理该信号。一个可移植程序必须在接收到该信号时中断,POSIX没有定义内核的下一步动作。如果进程继续运行,有些系统会中断进程,然而Linux允许进程继续运行,并且继续每秒给该进程发送一个SIGXCPU信号。一旦进程达到硬限制,将会收到SIGKILL信号并被中断。

RLIMIT_DATA

进程数据段和堆的大小,单位是字节。如果通过brk()来扩大数据段,并超出限制,将会失败并返回ENOMEM。

RLIMIT_FSIZE

文件可以创建的最大文件,单位是字节。如果进程扩展文件超出了限制,内核将发送SIGXFSZ信号。默认情况下,信号将终止进程。但是,进程也可以在系统调用失败返回EFBIG时选择自己捕捉和处理信号。

RLIMIT_LOCKS

进程可以拥有的文件锁的最大数量(参见第7章关于文件锁的讨论)。一旦达到最大值,任何试图获取额外锁的努力都会失败,返回ENOLCK。Linux 2.4.25内核移除了这一功能,在当前内核中,可以设定这一限制,但不会起任何作用。

RLIMIT_MEMLOCK

没有CAP_SYS_IPC权限的进程(非root进程)通过mlock()、mlockall()或者shmctl()能锁定的最多内存的字节数。当超过限制的时候,调用失败范围EPERM。实际上,实际限制向下舍入到整数个内存页。拥有CAP_SYS_IPC权限的进程可以锁定任意数量的内存页,此限制不再有效。在2.6.9内核前,该限制只局限于有CAP_SYS_IPC权限的进程,非特权进程根本不能锁定内存页。该限制项不属于POSIX标准,BSD首先引入了它。

RLIMIT_MSGQUEUE

用户可以在POSIX消息队列中分配的最多字节。如果新建的消息超出限制,mp_open()函数会失败返回ENOMEM。它不属于POSIX标准,发送在内核2.6.8中引入,该限制项是Linux所特有的。

RLIMIT_NICE

进程可以降低nice value(提高优先级)的最大值。本章前面已经说明了,普通进程只能提高其nice value(降低优先级)。这个限制允许管理员规定进程可以合法地提高优先级的级数。因为nice value可能是负值,内核用20-rlim_cur表示。因此,如果限制设置为40,进程nice value最低为-20(最高优先级)。Linux 2.6.12内核引入了这个限制。

RLIMIT_NOFILE

该值比进程可以打开的最多文件数大一。任何超出限制的操作都会失败,并返回EMFILE。在BSD中,此限制名字也可以是RLIMIT_OFILE。

RLIMIT_NPROC

指定某个用户在系统任意时刻允许的最多进程数。任何超出限制的操作都会失败,fork()调用会返回EAGAIN。此限制不属于POSIX标准,而是由BSD引入。

RLIMIT_RSS

指定进程可以驻留在内存中的最大页数(即驻留集大小RSS)。仅在早期的2.4内核中强制有该限制;当前内核允许设置该限制,但不强制。此限制不属于POSIX,由BSD引入。

RLIMIT_RTTIME

指定一个实时进程在没有发起阻塞的系统调用时,最多可以消耗的CPU时间上限(单位是微秒)。一旦进程发起了阻塞的系统调用,CPU时间就重新设置为0。该限制可以避免实时进程运行得不到控制而导致系统崩溃。在Linux内核版本2.6.25中引入了该限制,它是Linux所特有的。

RLIMIT_RTPRIO

指定没有CAP_SYS_NICE权限的进程可以拥有的最大实时优先级。通常,非特权进程不会要求实时调度。此限制不属于POSIX,由2.6.12内核引入并为Linux所特有。

RLIMIT_SIGPENDING

指定用户消息队列中最多信号数。请求更多的信号将失败,sigqueue()这样的系统调用将返回EAGAIN。注意,可以无视这个限制而将一个尚未排入队列的信号实例加入该队列。因此,总是可以向进程传递SIGKILL和SIGTERM信号。此限制不属于POSIX,由Linux独有。

RLIMIT_STACK

指定栈的最大字节长度。超出限制将收到SIGSEGV信号。

在Linux内核中,以进程为单位管理资源限制。子进程在fork时从父进程继承资源限制,这些限制在exec调用时会起作用。

默认的限制值

默认的限制值取决于3个变量:初始软限制、初始硬限制和系统管理员。内核设置了初始软限制和初始硬限制,如表6-1所示。内核在init进程中设置这些限制值,由于子进程会继承父进程的限制值,所有后续进程都会继承init的软硬限制值。

表6-1 默认的软硬资源限制

| 资源限制 | 软 限 制 | 硬 限 制 | | :----- | :----- | :----- | :----- | :----- | | RLIMIT_AS | RLIM_INFINITY | RLIM_INFINITY | | RLIMIT_CORE | 0 | RLIM_INFINITY | | RLIMIT_CPU | RLIM_INFINITY | RLIM_INFINITY | | RLIMIT_DATA | RLIM_INFINITY | RLIM_INFINITY | | RLIMIT_FSIZE | RLIM_INFINITY | RLIM_INFINITY | | RLIMIT_LOCKS | RLIM_INFINITY | RLIM_INFINITY | | RLIMIT_MEMLOCK | 8 pages | 8 pages | | RLIMIT_MSGQUEUE | 800 KB | 800 KB | | RLIMIT_NICE | 0 | 0 | | RLIMIT_NOFILE | 1 024 | 1 024 | | RLIMIT_NPROC | 0 (implies no limit) | 0 (implies no limit) | | RLIMIT_RSS | RLIM_INFINITY | RLIM_INFINITY | | RLIMIT_RTPRIO | 0 | 0 | | RLIMIT_SIGPENDING | 0 | 0 | | RLIMIT_STACK | 8 MB | RLIM_INFINITY |

可以通过两种方式改变默认限制:

  • 任何进程都可以在0到硬限制的范围内增加软限制,也可以减少硬限制,子进程在调用fork时会继承更新的限制值。
  • 有特殊权限的进程可以任意设置硬限制,子进程同样在调用fork时继承这些更新的限制值。

在正常的进程继承体系中,root进程很少会修改任何硬限制,因此,更多的是通过第一种方式修改默认限制,而不是第二种方式。实际上,对于进程的限制往往由用户通过shell设定,系统管理员可以进行设置来提供种类繁多的限制。比如在Bourne-again shell(bash)中,管理员可以使用ulimit命令来设置。注意,管理员不仅可以降低限制值,还可以提升软限制到硬限制,从而给用户提供更合理的限制。这一般是通过使用RLIMITSTACK,在很多系统上,该值都被设置为RLIM INFINITY。