每个进程都有一组资源限制,其中一些可以用getrlimit和setrlimit函数查询和更改。
#include <sys/resource.h> int getrlimit( int resource, struct rlimit *rlptr ); int setrlimit( int resource, const struct rlimit *rlptr ); 两个函数返回值:若成功则返回0,若出错则返回非0值
进程的资源限制通常是在系统初始化时由进程0建立的,然后由每个后续进程继承。每种实现都可以用自己的方法对各种限制做出调整。
对这两个函数的每一次调用都会指定一个资源以及一个指向下列结构的指针。
struct rlimit { rlim_t rlim_cur; /* soft limit: current limit */ rlim_t rlim_max; /* hard limit: maximum value for rlim_cur */ };
在更改资源限制时,须遵循下列三条规则:
(1)任何一个进程都可将一个软限制值更改为小于或等于其硬限制值。
(2)任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。这种降低对普通用户而言是不可逆的。
(3)只有超级用户进程可以提高硬限制值。
常量RLIM_INFINITY指定了一个无限量的限制。
这两个函数的resource参数取下列值之一:
RLIMIT_AS 进程可用存储区的最大总长度(字节)。这回影响sbrk函数和mmap函数。
RLIMIT_CORE core文件的最大字节数,若其值为0则阻止创建core文件。
RLIMIT_CPU CPU时间的最大量值(秒),当超过此软限制时,向该进程发送SIGXCPU信号。
RLIMIT_DATA 数据段的最大字节长度。这是初始化数据、非初始化数据以及堆的总和。
RLIMIT_FSIZE 可以创建的文件的最大字节长度。当超过此软限制时,则向该进程发送SIGXFSZ信号。
RLIMIT_LOCKS 一个进程可持有的文件锁的最大数(此数也包括Linux特有的文件租借数)。
RLIMIT_MEMLOCK 一个进程使用mlock(2)能够锁定在存储器中的最大字节长度。
RLIMIT_NOFILE 每个进程能打开的最大文件数。更改此限制将影响到sysconf函数在参数_SC_OPEN_MAX中的返回值。
RLIMIT_NPROC 每个实际用户ID可拥有的最大子进程数。更改此限制将影响到sysconf函数在参数_SC_CHILD_MAX中返回的值。
RLIMIT_RSS 最大驻内存集的字节长度(resident set size in bytes, RSS)。如果物理存储器供不应求,则内核将从进程处取回超过RSS的部分。
RLIMIT_SBSIZE 用户在任一给定时刻可以占用的套接字缓冲区的最大长度(字节)。(Linux 2.4.22不支持)
RLIMIT_STACK 栈的最大字节长度。
RLIMIT_VMEM 这是RLIMIT_AS的同义词。(Linux 2.4.22不支持)
资源限制影响到调用进程并由其子进程继承。这就意味着为了影响一个用户的所有后续进行,需将资源限制的设置构造在shell之中。Bsh、Bash和Ksh具有内置的ulimit命令,Csh具有内置的limit命令。
程序7-8 打印当前资源限制
[root@localhost apue]# cat prog7-8.c #include "apue.h" #if defined(BSD) || defined(MACOS) #include <sys/time.h> #define FMT "%10lld " #else #define FMT "%10ld " #endif #include <sys/resource.h> #define doit(name) pr_limits(#name, name) static void pr_limits(char *, int); int main(void) { #ifdef RLIMIT_AS doit(RLIMIT_AS); #endif doit(RLIMIT_CORE); doit(RLIMIT_CPU); doit(RLIMIT_DATA); doit(RLIMIT_FSIZE); #ifdef RLIMIT_LOCKS doit(RLIMIT_LOCKS); #endif #ifdef RLIMIT_MEMLOCK doit(RLIMIT_MEMLOCK); #endif doit(RLIMIT_NOFILE); #ifdef RLIMIT_NPROC doit(RLIMIT_NPROC); #endif #ifdef RLIMIT_RSS doit(RLIMIT_RSS); #endif #ifdef RLIMIT_SBSIZE doit(RLIMIT_SBSIZE); #endif doit(RLIMIT_STACK); #ifdef RLIMIT_VMEM doit(RLIMIT_VMEM #endif exit(0); } static void pr_limits(char *name, int resource) { struct rlimit limit; if(getrlimit(resource, &limit) < 0) err_sys("getrlimit error for %s", name); printf("%-14s ", name); if(limit.rlim_cur == RLIM_INFINITY) printf("(infinite) "); else printf(FMT, limit.rlim_cur); if(limit.rlim_max == RLIM_INFINITY) printf("(infinite) "); else printf(FMT, limit.rlim_max); putchar((int)' '); }
注意,在doit宏中使用了(也只能在宏中使用)ISO C的字符串创建运算符(#),以便为每个资源名产生字符串值。例如:
doit(RLIMIT_CORE);
这将由C预处理器扩展为:
pr_limits(“RLIMIT_CORE”, RLIMIT_CORE);
在Linux下运行此程序,得到:
[root@localhost apue]# ./prog7-8 RLIMIT_AS (infinite) (infinite) RLIMIT_CORE 0 (infinite) RLIMIT_CPU (infinite) (infinite) RLIMIT_DATA (infinite) (infinite) RLIMIT_FSIZE (infinite) (infinite) RLIMIT_LOCKS (infinite) (infinite) RLIMIT_MEMLOCK 32768 32768 RLIMIT_NOFILE 1024 1024 RLIMIT_NPROC 8192 8192 RLIMIT_RSS (infinite) (infinite) RLIMIT_STACK 10485760 (infinite)
本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。