进程资源限制

    每个进程都有一组资源限制,进程的资源限制通常是在系统初始化时由 0 进程建立的,然后由后续进程继承。每种实现都可以用自己的方法对资源限制做出调整。可以使用 getrlimit 和 setrlimit 函数来查询和修改进程的资源限制。
#include <sys/resource.h>

int getrlimit(int resource, struct rlimit *rlptr);
int setrlimit(int resource, const struct rlimit *rlptr);
                    /* 返回值:若成功,都返回 0;否则,都返回非 0 */

struct rlimit{
    rlim_t rlim_cur;        // soft limit: current limit
    rlim_t rlim_max;        // hard limit: maximum value for rlim_cur
};

    在更改资源限制时,须遵循下列 3 条规则。
    (1)任何一个进程都可将一个软限制值更改为小于或等于其硬限制值。
    (2)任何一个进程都可降低其硬限制值,但必须不小于其软限制值。这种降低对普通用户而言是不可逆的。
    (3)只有超级用户进程可以提高硬限制值。
    常量 RLIM_INFINITY 指定了一个无限量的限制。
    下图显示了 resource 参数的可选值中哪些是由 Single UNIX Specification 定义以及常用UNIX 系统的支持情况。

    其中各个值的说明如下。
    * RLIMIT_AS:进程总的可用存储空间的最大长度(字节)。这影响到 sbrk 函数和 mmap 函数。
    * RLIMIT_CORE:core 文件的最大字节数,若其值为 0 则阻止创建 core 文件。
    * RLIMIT_CPU:CPU 时间的最大量值(秒),当超过此软限制时,向进程发送 SIGXCPU 信号。
    * RLIMIT_DATA:数据段的最大字节长度。这是初始化数据、非初始化以及堆的总和。
    * RLIMIT_FSIZE:可以创建的文件的最大字节长度。当超过此软限制时,则向该进程发送 SIGXFSZ 信号。
    * RLIMIT_MEMLOCK:一个进程使用 mlock(2) 能够锁定在存储空间中的最大字节长度。
    * RLIMIT_MSQQUEUE:进程为 POSIX 消息队列可分配的最大存储字节数。
    * RLIMIT_NICE:为了影响进程的调度优先级,nice 值可设置的最大限制。
    * RLIMIT_NOFILE:每个进程能打开的最多文件数。更改此限制将影响到 sysconf 函数在参数 _SC_OPEN_MAX 中返回的值。
    * RLIMIT_NPROC:每个实际用户 ID 可拥有的最大子进程数。更改此限制将影响到 sysconf 函数在参数 _SC_CHILD_MAX 中返回的值。
    * RLIMIT_NPTS:用户可同时打开的伪终端的最大数量。
    * RLIMIT_RSS:最大驻内存集字节长度(resident set size in bytes,RSS)。如果可用的物理存储器非常少,则内核将从进程处取回超过 RSS 的部分。
    * RLIMIT_SBSIZE:在任一给定时刻,一个用户可以占用的套接字缓冲区的最大长度(字节)。
    * RLIMIT_SIGPENDING:一个进程可排队的信号最大数量。这个限制是 sigqueue 函数实施的。
    * RLIMIT_STACK:栈的最大字节长度。
    * RLIMIT_SWAP:用户可消耗的交换空间的最大字节数。
    * RLIMIT_VMEM:RLIMIT_AS 的同义词。
    资源限制影响到调用进程并由其子进程继承。这意味着,为了影响一个用户的所有后续进程,需要将资源限制的设置构造在 shell 中,比如 Bourne shell、GNU Bourne-again shell 和 Kom shell 就具有内置的 ulimit 命令,C shell 具有内置的 limit 命令。
    下列程序打印由系统支持的所有资源当前的软限制和硬限制(注意,有些平台定义 rlim_t 为 unsigned long long 而非 unsigned long。有些限制作用于文件大小,因此 rlim_t 类型必须足够大才能表示文件大小限制。为了避免使用错误的格式说明而导致编译器警告,通常会首先把限制复制到 64 位整型,这样只需处理一种格式)。
#include <stdio.h>
#include <stdlib.h>
#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_MEMLOCK
	doit(RLIMIT_MEMLOCK);
#endif
#ifdef RLIMIT_MSGQUEUE
	doit(RLIMIT_MSGQUEUE);
#endif
#ifdef RLIMIT_NICE
	doit(RLIMIT_NICE);
#endif
	doit(RLIMIT_NOFILE);
#ifdef RLIMIT_NPROC
	doit(RLIMIT_NPROC);
#endif
#ifdef RLIMIT_NPTS
	doit(RLIMIT_NPTS);
#endif
#ifdef RLIMIT_RSS
	doit(RLIMIT_RSS);
#endif
#ifdef RLIMIT_SBSIZE
	doit(RLIMIT_SBSIZE);
#endif
#ifdef RLIMIT_SIGPENDING
	doit(RLIMIT_SIGPENDING);
#endif
	doit(RLIMIT_STACK);
#ifdef RLIMIT_SWAP
	doit(RLIMIT_SWAP);
#endif
#ifdef RLIMIT_VMEM
	doit(RLIMIT_VMEM);
#endif
	exit(0);
}

static void pr_limits(char *name, int resource){
	struct rlimit	limit;
	unsigned long long lim;
	if(getrlimit(resource, &limit) < 0){
		printf("getrlimit error for %s\n", name);
		return;
	}
	printf("%-14s ", name);
	if(limit.rlim_cur == RLIM_INFINITY){
		printf("(infinite) ");
	}else{
		lim = limit.rlim_cur;
		printf("%10lld ", lim);
	}
	if(limit.rlim_max == RLIM_INFINITY){
		printf("(infinite)");
	}else{
		lim = limit.rlim_max;
		printf("%10lld", lim);
	}
	putchar((int)'\n');
}

    注意,在 doit 宏中使用了 ISO C 的字符串创建运算符“#”,以便为每个资源名产生字符串值。
    Linux 系统上的运行结果如下。
$ ./resourceLimit.out 
RLIMIT_AS      (infinite) (infinite)
RLIMIT_CORE             0 (infinite)
RLIMIT_CPU     (infinite) (infinite)
RLIMIT_DATA    (infinite) (infinite)
RLIMIT_FSIZE   (infinite) (infinite)
RLIMIT_MEMLOCK      65536      65536
RLIMIT_MSGQUEUE     819200     819200
RLIMIT_NICE             0          0
RLIMIT_NOFILE       65535      65535
RLIMIT_NPROC         1024      65535
RLIMIT_RSS     (infinite) (infinite)
RLIMIT_SIGPENDING       3810       3810
RLIMIT_STACK     10485760 (infinite)

猜你喜欢

转载自aisxyz.iteye.com/blog/2391218
今日推荐