Process Resource Limits

As system resources are finite, every process is restrained by certain operating system-imposed limits. At the command line, the ulimit command (which is actually a built-in command found in the Bourne shell [ /bin/sh ]) provides the user with a means to display and modify current system limits available to the shell and the processes that are started by it. [8]

[8] The C shell ( /bin/csh ) provides a somewhat similar built-in command called limit .

The command ulimit -Ha displays the hard limits for the system. The hard limits can be increased only by the superuser. An example showing the hard limits of a system is shown in Figure 2.13.

Figure 2.13 Typical hard limits on a Linux system.

linux$ ulimit -Ha core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited file size (blocks, -f) unlimited max locked memory (kbytes, -l) unlimited max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 stack size (kbytes, -s) unlimited cpu time (seconds, -t) unlimited max user processes (-u) 4095 virtual memory (kbytes, -v) unlimited

A soft limit, displayed when ulimit is passed the -Sa (Soft, all) command-line option, is a limit that can be set by the user. A soft limit is typically lower than the established hard limit. Note that the limits for the current process on this system are slightly less for stack size, as shown in Figure 2.14.

Figure 2.14 Individual process resource limits.

linux$ ulimit -Sa core file size (blocks, -c) unlimited data seg size (kbytes, -d) unlimited file size (blocks, -f) unlimited max locked memory (kbytes, -l) unlimited max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 4095 virtual memory (kbytes, -v) unlimited

Resource limit information for a process can be obtained in a programming environment as well. Historically, the ulimit system call was used to obtain part of this information. In more recent versions of the operating system the ulimit system call has been superseded by the getrlimit / setrlimit calls described below. However, ulimit still bears a cursory investigation, as it is sometimes found in legacy code (Table 2.17).

Table 2.17. Summary of the ulimit System Call.

Include File(s)

Manual Section

3

Summary

long ulimit(int cmd /* , long newlimit */ );

Return

Success

Failure

Sets errno

Nonnegative long integer

1

Yes

The argument cmd can take one of four different values:

  1. Obtain file size limit for this process. The value returned is in units of 512-byte blocks.
  2. Set the file size limit to the value indicated by newlimit . Non-superusers only can decrease the file size limit. This is the only command in which the argument newlimit is used.
  3. Obtain the maximum break value. This option is not supported by Linux.
  4. Return the maximum number of files that the calling process can open.

If ulimit is successful, it returns a positive integer value; otherwise , it returns a -1 and sets the value in errno (Table 2.18).

Table 2.18. ulimit Error Messages.

#

Constant

perror Message

Explanation

13

EPERM

Permission denied

Calling process is not superuser.

22

EINVAL

Invalid argument

The value for cmd is invalid.

The newer getrlimit / setrlimit system calls provide the process more complete access to system resource limits (Table 2.19).

Table 2.19. Summary of the getrlimit/setrlimit System Calls.

Include File(s)

 

Manual Section

2

Summary

int getrlimit(int resource, struct rlimit *rlim); int setrlimit(int resource, const struct rlimit *rlim);

Return

Success

Failure

Sets errno

-1

Yes

The rlimit structure:

struct rlimit { rlimit_t rlim_cur; /* current (soft) limit */ rlimit_t rlim_max; /* hard limit */ };

along with a number of defined constants used by the two functions:

RLIMIT_CPU /* CPU time in seconds */ RLIMIT_FSIZE /* Maximum filesize */ RLIMIT_DATA /* max data size */ RLIMIT_STACK /* max stack size */ RLIMIT_CORE /* max core file size */ RLIMIT_RSS /* max resident set size */ RLIMIT_NPROC /* max number of processes */ RLIMIT_NOFILE /* max number of open files */ RLIMIT_MEMLOCK /* max locked-in-memory address space*/ RLIMIT_AS /* address space (virtual memory) limit */ RLIMIT_INFINITY /* actual value for 'unlimited' */

are found in the header file and its associated include files. A program using the getrlimit system call is shown in Program 2.3.

Program 2.3 Displaying resource limit information.

/* Using getrlimt to display system resource limits */ #include + #include #include #include using namespace std; int 10 main( ){ struct rlimit plimit; char *label[ ]={"CPU time", "File size", "Data segment", "Stack segment", "Core size","Resident set size", + "Number of processes", "Open files", "Locked-in-memory", "Virtual memory", 0}; int constant[]= { RLIMIT_CPU , RLIMIT_FSIZE, RLIMIT_DATA , RLIMIT_STACK, 20 RLIMIT_CORE , RLIMIT_RSS, RLIMIT_NPROC , RLIMIT_NOFILE, RLIMIT_MEMLOCK, RLIMIT_AS }; for (int i = 0; label[i]; ++i) { + getrlimit(constant[i], &plimit); cout << setw(20) << label[i] << " Current: " << setw(10) << plimit.rlim_cur << " Max: " << setw(10) << plimit.rlim_max << endl; } 30 return 0; }

The output sequence from this program (Figure 2.15) is comparable to the output of the system-level ulimit command shown earlier.

Figure 2.15 Program 2.3 output.

linux$ p2.3 CPU time Current: 4294967295 Max: 4294967295 File size Current: 4294967295 Max: 4294967295 Data segment Current: 4294967295 Max: 4294967295 Stack segment Current: 8388608 Max: 4294967295 Core size Current: 4294967295 Max: 4294967295 Resident set size Current: 4294967295 Max: 4294967295 Number of processes Current: 16383 Max: 16383 Open files Current: 1024 Max: 1024 Locked-in-memory Current: 4294967295 Max: 4294967295 Virtual memory Current: 4294967295 Max: 4294967295

The setrlimit system call, like the ulimit call, can be used only by the non-superuser to decrease resource limits. If these system calls are successful, they return a 0; otherwise, they return a -1 and set the value in errno (Table 2.20).

Table 2.20. getrlimit/setrlimit Error Messages.

#

Constant

perror Message

Explanation

13

EPERM

Permission denied

Calling process is not superuser.

22

EINVAL

Invalid argument

The value for resource is invalid.

EXERCISE

In the Bourne (or BASH /bin/bash ) shell issue the command ulimit -u 2 followed by the command ls -l . Explain what happens. How did you correct the situation? If in the C Shell ( /bin/csh or /bin/tcsh ), replace the ulimit command with limit ma 2 ).

Additional process limit information can be obtained from the sysconf library function (Table 2.21).

Table 2.21. Summary of the sysconf Library Function.

Include File(s)

Manual Section

3

Summary

long sysconf(int name );

Return

Success

Failure

Sets errno

Nonnegative long integer

-1

No (?)

The sysconf function is passed an integer name value (usually in the form of a defined constant) that indicates the limit requested . If successful, the function returns the long integer value associated with the limit or a value of 0 or 1 if the limit is available or not. If the sysconf function fails, it returns a -1 and does not set the value in errno . The limits that sysconf knows about are defined as constants in the header file . [9] In past versions of the operating system, some of these limit values were found in the header file . The constants for some of the more commonly queried limits are listed below:

[9] Actually, this is a bit of a fudge. The include file often includes yet another file that has the constant definitions. There is logic in the file to include the proper file based on the standard being met (POSIX.1, etc.). At present the actual definitions are found in < bits/confname.h >which is never to be included directly by the programmer.

_SC_ARG_MAX /* space for argv & envp */ _SC_CHILD_MAX /* max children per process */ _SC_CLK_TCK /* clock ticks / sec */ _SC_STREAM_MAX /* max # of data streams per process */ _SC_TZNAME_MAX /* max # of bytes in timezone name spec. */ _SC_OPEN_MAX /* max open files per process */ _SC_JOB_CONTROL /* do we have job control? */ _SC_SAVED_IDS /* do we have saved uid/gids? */ _SC_VERSION /* POSIX version supported YYYYMML format*/

Program 2.4, which displays the values associated with the limits for a system, is shown below.

Program 2.4 Displaying system limits.

File : p2.4.cxx /* Using sysconf to display system limits */ #include + #include #include #include using namespace std; int 10 main( ){ char *limits[ ]={"Max size of argv + envp", "Max # of child processes", "Ticks / second", "Max # of streams", + "Max # of bytes in a TZ name", "Max # of open files", "Job control supported?", "Saved IDs supported?", "Version of POSIX supported", 20 0}; int constant[ ]={ _SC_ARG_MAX, _SC_CHILD_MAX, _SC_CLK_TCK, _SC_STREAM_MAX, _SC_TZNAME_MAX, _SC_OPEN_MAX, _SC_JOB_CONTROL,_SC_SAVED_IDS, + _SC_VERSION }; for (int i=0; limits[i]; ++i) { cout << setw(30) << limits[i] << " " << sysconf(constant[i]) << endl; } 30 return 0; }

When run on a local system, Program 2.4 produced the output shown in Figure 2.16.

Figure 2.16 Output of Program 2.4.

linux$ p2.4 Max size of argv + envp 131072 Max # of child processes 999 Ticks / second 100 Max # of streams 16 Max # of bytes in a TZ name 3 Max # of open files 1024 Job control supported? 1 Saved IDs supported? 1 Version of POSIX supported 199506

If the sysconf function fails due to an invalid name value, a -1 is returned. The manual page indicates errno will not be set; however, some versions of Linux set errno to ENIVAL , indicating an invalid argument.

Категории