7 . 11 getrlimit和setrlimit函数
每个进程都有一组资源限制,其中某一些可以用getrlimit和setrlimit函数查询和更改。
#include <sys/time.h>
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit * rlptr) ;
int setrlimit(int resource, const struct rlimit * rlptr) ;
//两个函数返回:若成功则为0,若出错则为非0
这两个函数在Single UNIX Specification中定义为XSI扩展。进程的资源限制通常是在系统初始化时由进程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) 只有超级用户可以提高硬限制。
一个无限量的限制由常数R L I M _ I N F I N I T Y指定。
这两个函数的resource参数取下列值之一。注意并非所有资源限制都受到SVR4和4 . 3 + BSD的支持。
• RLIMIT_AS 进程可用存储区的最大总长度(字节),这会影响sbrk函数和mmap函数;
• RLIMIT_CORE c o r e文件的最大字节数,若其值为0则阻止创建c o r e文件。
• RLIMIT_CPU CPU时间的最大量值(秒),当超过此软限制时,向该进程发送S I G X CPU信号。
• RLIMIT_DATA 数据段的最大字节长度。
• RLIMIT_FSIZE 可以创建的文件的最大字节长度。当超过此软限制时,则向该进程发送S I G X F S Z信号。
• RLIMIT_LOCKS 一个进程可持有的文件锁的最大数。
• RLIMIT_MEMLOCK 锁定在存储器地址空间(尚未实现)。
• RLIMIT_NOFILE 每个进程能打开的最多文件数。更改此限制将影响到s y s c o n f函数在参数_ S C _ O P E N _ M A X中返回的值。
• RLIMIT_NPROC 每个实际用户I D所拥有的最大子进程数。更改此限制将影响到s y s c o n f函数在参数_ S C _ C H I L D _ M A X中返回的值。
• RLIMIT_OFILE 与SVR4的R L I M I T _ N O F I L E相同。
• RLIMIT_RSS 最大驻内存集字节长度(R S S)。如果物理存储器供不应求,则内核将从进程处取回超过R S S的部分。
• RLIMIT_STACK 栈的最大字节长度。
• RLIMIT_VMEM 可映照地址空间的最大字节长度。这影响到m m a p函数。
资源限制影响到调用进程并由其子进程继承。这就意味着为了影响一个用户的所有后续进程,需将资源限制设置构造在shell之中。确实,Bourne shell和Korn Shell具有内部ulimit命令,C shell具有内部l i m i t命令。( umask和chdir函数也必须是shell内部的。)
实例
程序7 - 8打印由系统支持的对所有资源的当前软限制和硬限制。为了在各种实现上编译该程序,我们已经有条件地包括了各种不同的资源名,另请注意,有些平台定义rlim_t为unsigned long long而非unsigned long,对于此种平台,必须使用不同的printf格式。
#include <stdio.h>
#include <stdlib.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)
perror("getrlimit error");
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) '\n');
}
注意,在doit宏中使用了新的ANSI C字符串创建算符( # ),以便为每个资源名产生字符串值。例如:
doit ( RLIMIT_CORE ) ;
这将由C预处理程序扩展为:
pr_limits("RLIMIT_CORE", RLIMIT_CORE);
在Ubuntu上运行该程序得到:
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 65536 65536
RLIMIT_NOFILE 1024 1024
RLIMIT_NPROC (infinite) (infinite)
RLIMIT_RSS (infinite) (infinite)
RLIMIT_STACK 8388608 (infinite)