Advanced Programming in the UNIX Environment, Second Edition (Addison-Wesley Professional Computing Series)

7.11. getrlimit and setrlimit Functions

Every process has a set of resource limits, some of which can be queried and changed by the geTRlimit and setrlimit functions.

[View full width]

#include <sys/resource.h> int getrlimit(int resource, struct rlimit *rlptr); int setrlimit(int resource, const struct rlimit *rlptr);

Both return: 0 if OK, nonzero on error

These two functions are defined as XSI extensions in the Single UNIX Specification. The resource limits for a process are normally established by process 0 when the system is initialized and then inherited by each successive process. Each implementation has its own way of tuning the various limits.

Each call to these two functions specifies a single resource and a pointer to the following structure:

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

Three rules govern the changing of the resource limits.

  1. A process can change its soft limit to a value less than or equal to its hard limit.

  2. A process can lower its hard limit to a value greater than or equal to its soft limit. This lowering of the hard limit is irreversible for normal users.

  3. Only a superuser process can raise a hard limit.

An infinite limit is specified by the constant RLIM_INFINITY.

The resource argument takes on one of the following values. Figure 7.15 shows which limits are defined by the Single UNIX Specification and supported by each implementation.

Figure 7.15. Support for resource limits

Limit

XSI

FreeBSD 5.2.1

Linux 2.4.22

Mac OS X 10.3

Solaris 9

RLIMIT_AS

 

 

RLIMIT_CORE

RLIMIT_CPU

RLIMIT_DATA

RLIMIT_FSIZE

RLIMIT_LOCKS

  

  

RLIMIT_MEMLOCK

 

 

RLIMIT_NOFILE

RLIMIT_NPROC

 

 

RLIMIT_RSS

 

 

RLIMIT_SBSIZE

 

   

RLIMIT_STACK

RLIMIT_VMEM

 

  

RLIMIT_AS

The maximum size in bytes of a process's total available memory. This affects the sbrk function (Section 1.11) and the mmap function (Section 14.9).

RLIMIT_CORE

The maximum size in bytes of a core file. A limit of 0 prevents the creation of a core file.

RLIMIT_CPU

The maximum amount of CPU time in seconds. When the soft limit is exceeded, the SIGXCPU signal is sent to the process.

RLIMIT_DATA

The maximum size in bytes of the data segment: the sum of the initialized data, uninitialized data, and heap from Figure 7.6.

RLIMIT_FSIZE

The maximum size in bytes of a file that may be created. When the soft limit is exceeded, the process is sent the SIGXFSZ signal.

RLIMIT_LOCKS

The maximum number of file locks a process can hold. (This number also includes file leases, a Linux-specific feature. See the Linux fcntl(2) manual page for more information.)

RLIMIT_MEMLOCK

The maximum amount of memory in bytes that a process can lock into memory using mlock(2).

RLIMIT_NOFILE

The maximum number of open files per process. Changing this limit affects the value returned by the sysconf function for its _SC_OPEN_MAX argument (Section 2.5.4). See Figure 2.16 also.

RLIMIT_NPROC

The maximum number of child processes per real user ID. Changing this limit affects the value returned for _SC_CHILD_MAX by the sysconf function (Section 2.5.4).

RLIMIT_RSS

Maximum resident set size (RSS) in bytes. If available physical memory is low, the kernel takes memory from processes that exceed their RSS.

RLIMIT_SBSIZE

The maximum size in bytes of socket buffers that a user can consume at any given time.

RLIMIT_STACK

The maximum size in bytes of the stack. See Figure 7.6.

RLIMIT_VMEM

This is a synonym for RLIMIT_AS.

The resource limits affect the calling process and are inherited by any of its children. This means that the setting of resource limits needs to be built into the shells to affect all our future processes. Indeed, the Bourne shell, the GNU Bourne-again shell, and the Korn shell have the built-in ulimit command, and the C shell has the built-in limit command. (The umask and chdir functions also have to be handled as shell built-ins.)

Example

The program in Figure 7.16 prints out the current soft limit and hard limit for all the resource limits supported on the system. To compile this program on all the various implementations, we have conditionally included the resource names that differ. Note also that we must use a different printf format on platforms that define rlim_t to be an unsigned long long instead of an unsigned long.

Note that we've used the ISO C string-creation operator (#) in the doit macro, to generate the string value for each resource name. When we say

doit(RLIMIT_CORE);

the C preprocessor expands this into

pr_limits("RLIMIT_CORE", RLIMIT_CORE);

Running this program under FreeBSD gives us the following:

$ ./a.out RLIMIT_CORE (infinite) (infinite) RLIMIT_CPU (infinite) (infinite) RLIMIT_DATA 536870912 536870912 RLIMIT_FSIZE (infinite) (infinite) RLIMIT_MEMLOCK (infinite) (infinite) RLIMIT_NOFILE 1735 1735 RLIMIT_NPROC 867 867 RLIMIT_RSS (infinite) (infinite) RLIMIT_SBSIZE (infinite) (infinite) RLIMIT_STACK 67108864 67108864 RLIMIT_VMEM (infinite) (infinite)

Solaris gives us the following results:

$ ./a.out RLIMIT_AS (infinite) (infinite) RLIMIT_CORE (infinite) (infinite) RLIMIT_CPU (infinite) (infinite) RLIMIT_DATA (infinite) (infinite) RLIMIT_FSIZE (infinite) (infinite) RLIMIT_NOFILE 256 65536 RLIMIT_STACK 8388608 (infinite) RLIMIT_VMEM (infinite) (infinite)

Figure 7.16. Print the current resource limits

#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)'\n'); }

Exercise 10.11 continues the discussion of resource limits, after we've covered signals.

    Категории