Team BBL
Previous Page Next Page

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.

  #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.

    Team BBL
    Previous Page Next Page