getrlimit setrlimit

本文介绍了Linux系统中用于设置和获取进程资源限制的getrlimit和setrlimit函数。包括通过ulimit命令查看资源限制,使用C语言实现的测试程序展示各种资源限制的实际值,并详细解释了每个资源限制的具体含义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍资源限制函数getrlimit, setrlimit,当然仍是man大法好。

1. 首先看下ulimit -a

wln@iZ232ngsvp8Z:~/2015/11> ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3827
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) 422620
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 3827
virtual memory          (kbytes, -v) 397760
file locks                      (-x) unlimited


2. 测试程序

#include <sys/time.h>
#include <sys/resource.h>
#include <stdio.h>

int limitArray[]={
  RLIMIT_AS,
  RLIMIT_CORE,
  RLIMIT_CPU,
  RLIMIT_DATA,
  RLIMIT_FSIZE,
  RLIMIT_MEMLOCK,
  RLIMIT_MSGQUEUE,
  RLIMIT_NICE,
  RLIMIT_NOFILE,
  RLIMIT_NPROC,
  RLIMIT_RSS,
  RLIMIT_RTPRIO,
  RLIMIT_LOCKS,
  //RLIMIT_RTTIME,
  RLIMIT_SIGPENDING,
  RLIMIT_STACK
};


int main()
{
  struct rlimit *limit;
  int len=sizeof(limitArray)/sizeof(int);
  int i=0;
  while(i<len)
  {
      if(getrlimit(limitArray[i],limit) != 0)
      {
        printf("%d %m\n",i);
      }
      else
      {
         printf("%2d: cur:%d  %d\n",i,limit->rlim_cur,limit->rlim_max);
      }
      i=i+1;
  }

  //set core limit
  limit->rlim_cur = RLIM_INFINITY;
  limit->rlim_max = RLIM_INFINITY;
  if(setrlimit(RLIMIT_CORE, limit) !=0)
  {
    printf("set limit failed %m\n");
  }
  else
  {
    printf("set limit ok\n");
  }
 
}

执行结果:

wln@iZ232ngsvp8Z:~/2015/11> ./getrlimit1
 0: cur:407306240  -1
 1: cur:-1  -1
 2: cur:-1  -1
 3: cur:-1  -1
 4: cur:-1  -1
 5: cur:65536  262144
 6: cur:819200  819200
 7: cur:0  0
 8: cur:65535  65535
 9: cur:3827  3827
10: cur:432762880  -1
11: cur:0  0
12: cur:-1  -1
13: cur:3827  3827
14: cur:8388608  -1
set limit ok


3. man

NAME
       getrlimit, setrlimit - get/set resource limits

SYNOPSIS
       #include <sys/time.h>
       #include <sys/resource.h>

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

DESCRIPTION
       getrlimit() and setrlimit() get and set resource limits respectively.  Each resource has an associated soft and hard limit,
       as defined by the rlimit structure (the rlim argument to both getrlimit() and setrlimit()):

           struct rlimit {
               rlim_t rlim_cur;  /* Soft limit */
               rlim_t rlim_max;  /* Hard limit (ceiling for rlim_cur) */
           };

       The soft limit is the value that the kernel enforces for the corresponding resource.  The hard limit acts as a ceiling  for
       the  soft  limit:  an unprivileged process may only set its soft limit to a value in the range from 0 up to the hard limit,
       and (irreversibly) lower its hard limit.  A privileged process (under Linux: one with the CAP_SYS_RESOURCE capability)  may
       make arbitrary changes to either limit value.

       The  value RLIM_INFINITY denotes no limit on a resource (both in the structure returned by getrlimit() and in the structure
       passed to setrlimit()).

       resource must be one of:

       RLIMIT_AS
              The maximum size of the process's virtual memory (address space) in bytes.  This  limit  affects  calls  to  brk(2),
              mmap(2)  and  mremap(2), which fail with the error ENOMEM upon exceeding this limit.  Also automatic stack expansion
              will fail (and generate a SIGSEGV that kills the process if no alternate stack has been made available  via  sigalt-
              stack(2)).   Since  the  value is a long, on machines with a 32-bit long either this limit is at most 2 GiB, or this
              resource is unlimited.

       RLIMIT_CORE
              Maximum size of core file.  When 0 no core dump files are created.  When non-zero, larger  dumps  are  truncated  to
              this size.

       RLIMIT_CPU
              CPU  time  limit  in  seconds.   When  the process reaches the soft limit, it is sent a SIGXCPU signal.  The default
              action for this signal is to terminate the process.  However, the signal can be caught, and the handler  can  return
              control  to the main program.  If the process continues to consume CPU time, it will be sent SIGXCPU once per second
              until the hard limit is reached, at which time it is sent SIGKILL.  (This latter point describes Linux  2.2  through
              2.6  behavior.   Implementations  vary in how they treat processes which continue to consume CPU time after reaching
              the soft limit.  Portable applications that need to catch this signal should perform  an  orderly  termination  upon
              first receipt of SIGXCPU.)

       RLIMIT_DATA
              The maximum size of the process's data segment (initialized data, uninitialized data, and heap).  This limit affects
              calls to brk(2) and sbrk(2), which fail with the error ENOMEM upon encountering the soft limit of this resource.

       RLIMIT_FSIZE
              The maximum size of files that the process may create.  Attempts to extend a file beyond this limit result in deliv-
              ery of a SIGXFSZ signal.  By default, this signal terminates a process, but a process can catch this signal instead,
              in which case the relevant system call (e.g., write(2), truncate(2)) fails with the error EFBIG.

       RLIMIT_LOCKS (Early Linux 2.4 only)
              A limit on the combined number of flock(2) locks and fcntl(2) leases that this process may establish.

       RLIMIT_MEMLOCK
              The maximum number of bytes of memory that may be locked into RAM.  In effect this limit  is  rounded  down  to  the
              nearest  multiple  of  the system page size.  This limit affects mlock(2) and mlockall(2) and the mmap(2) MAP_LOCKED
              operation.  Since Linux 2.6.9 it also affects the shmctl(2) SHM_LOCK operation, where it sets a maximum on the total
              bytes  in shared memory segments (see shmget(2)) that may be locked by the real user ID of the calling process.  The
              shmctl(2) SHM_LOCK locks are accounted for separately from the per-process memory  locks  established  by  mlock(2),
              mlockall(2),  and mmap(2) MAP_LOCKED; a process can lock bytes up to this limit in each of these two categories.  In
              Linux kernels before 2.6.9, this limit controlled the amount of memory that could be locked by a privileged process.
              Since  Linux  2.6.9, no limits are placed on the amount of memory that a privileged process may lock, and this limit
              instead governs the amount of memory that an unprivileged process may lock.

       RLIMIT_MSGQUEUE (Since Linux 2.6.8)
              Specifies the limit on the number of bytes that can be allocated for POSIX message queues for the real  user  ID  of
              the calling process.  This limit is enforced for mq_open(3).  Each message queue that the user creates counts (until
              it is removed) against this limit according to the formula:

                  bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) +
                          attr.mq_maxmsg * attr.mq_msgsize

              where attr is the mq_attr structure specified as the fourth argument to mq_open(3).

              The first addend in the formula, which includes sizeof(struct msg_msg *) (4 bytes on Linux/i386), ensures  that  the
              user  cannot create an unlimited number of zero-length messages (such messages nevertheless each consume some system
              memory for bookkeeping overhead).

       RLIMIT_NICE (since Linux 2.6.12, but see BUGS below)
              Specifies a ceiling to which the process's nice value can be raised using setpriority(2)  or  nice(2).   The  actual
              ceiling for the nice value is calculated as 20 - rlim_cur.  (This strangeness occurs because negative numbers cannot
              be specified as resource limit values, since they typically have special meanings.  For example, RLIM_INFINITY typi-
              cally is the same as -1.)

       RLIMIT_NOFILE
              Specifies  a value one greater than the maximum file descriptor number that can be opened by this process.  Attempts
              (open(2), pipe(2), dup(2), etc.)  to exceed this limit yield the error EMFILE.  (Historically, this limit was  named
              RLIMIT_OFILE on BSD.)

       RLIMIT_NPROC
              The  maximum  number of processes (or, more precisely on Linux, threads) that can be created for the real user ID of
              the calling process.  Upon encountering this limit, fork(2) fails with the error EAGAIN.

       RLIMIT_RSS
              Specifies the limit (in pages) of the process's resident set (the number of virtual pages resident  in  RAM).   This
              limit only has effect in Linux 2.4.x, x < 30, and there only affects calls to madvise(2) specifying MADV_WILLNEED.

       RLIMIT_RTPRIO (Since Linux 2.6.12, but see BUGS)
              Specifies  a  ceiling  on  the  real-time  priority that may be set for this process using sched_setscheduler(2) and
              sched_setparam(2).

       RLIMIT_RTTIME (Since Linux 2.6.25)
              Specifies a limit on the amount of CPU time that a process scheduled under a real-time scheduling policy may consume
              without  making  a blocking system call.  For the purpose of this limit, each time a process makes a blocking system
              call, the count of its consumed CPU time is reset to zero.  The CPU time count is not reset if the process continues
              trying to use the CPU but is preempted, its time slice expires, or it calls sched_yield(2).

              Upon  reaching  the soft limit, the process is sent a SIGXCPU signal.  If the process catches or ignores this signal
              and continues consuming CPU time, then SIGXCPU will be generated once each second until the hard limit  is  reached,
              at which point the process is sent a SIGKILL signal.

              The intended use of this limit is to stop a runaway real-time process from locking up the system.

       RLIMIT_SIGPENDING (Since Linux 2.6.8)
              Specifies  the  limit on the number of signals that may be queued for the real user ID of the calling process.  Both
              standard and real-time signals are counted for the purpose of checking this  limit.   However,  the  limit  is  only
              enforced  for sigqueue(2); it is always possible to use kill(2) to queue one instance of any of the signals that are
              not already queued to the process.

       RLIMIT_STACK
              The maximum size of the process stack, in bytes.  Upon reaching this limit, a SIGSEGV signal is generated.  To  han-
              dle this signal, a process must employ an alternate signal stack (sigaltstack(2)).

              Since Linux 2.6.23, this limit also determines the amount of space used for the process's command-line arguments and
              environment variables; for details, see execve(2).

RETURN VALUE
       On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.

ERRORS
       EFAULT rlim points outside the accessible address space.

       EINVAL resource is not valid; or, for setrlimit(): rlim->rlim_cur was greater than rlim->rlim_max.

       EPERM  An unprivileged process tried to use setrlimit() to increase a soft or hard limit above the current hard limit;  the
              CAP_SYS_RESOURCE  capability  is required to do this.  Or, the process tried to use setrlimit() to increase the soft
              or hard RLIMIT_NOFILE limit above the current kernel maximum (NR_OPEN).

CONFORMING TO
       SVr4, 4.3BSD, POSIX.1-2001.  RLIMIT_MEMLOCK and RLIMIT_NPROC derive from BSD and are not specified  in  POSIX.1-2001;  they
       are  present  on the BSDs and Linux, but on few other implementations.  RLIMIT_RSS derives from BSD and is not specified in
       POSIX.1-2001;  it  is  nevertheless  present  on  most  implementations.   RLIMIT_MSGQUEUE,   RLIMIT_NICE,   RLIMIT_RTPRIO,
       RLIMIT_RTTIME, and RLIMIT_SIGPENDING are Linux-specific.

NOTES
       A child process created via fork(2) inherits its parent's resource limits.  Resource limits are preserved across execve(2).

       One can set the resource limits of the shell using the built-in ulimit command (limit in  csh(1)).   The  shell's  resource
       limits are inherited by the processes that it creates to execute commands.

BUGS
       In  older  Linux kernels, the SIGXCPU and SIGKILL signals delivered when a process encountered the soft and hard RLIMIT_CPU
       limits were delivered one (CPU) second later than they should have been.  This was fixed in kernel 2.6.8.

       In 2.6.x kernels before 2.6.17, a RLIMIT_CPU limit of 0 is wrongly treated as "no limit" (like RLIM_INFINITY).  Since Linux
       2.6.17, setting a limit of 0 does have an effect, but is actually treated as a limit of 1 second.

       A kernel bug means that RLIMIT_RTPRIO does not work in kernel 2.6.12; the problem is fixed in kernel 2.6.13.

       In  kernel 2.6.12, there was an off-by-one mismatch between the priority ranges returned by getpriority(2) and RLIMIT_NICE.
       This had the effect that actual ceiling for the nice value was calculated as  19 - rlim_cur.   This  was  fixed  in  kernel
       2.6.13.

       Kernels  before  2.4.22  did  not  diagnose  the  error  EINVAL  for  setrlimit()  when  rlim->rlim_cur  was  greater  than
       rlim->rlim_max.

SEE ALSO
       dup(2), fcntl(2), fork(2), getrusage(2), mlock(2), mmap(2), open(2), quotactl(2),  sbrk(2),  shmctl(2),  sigqueue(2),  mal-
       loc(3), ulimit(3), core(5), capabilities(7), signal(7)

COLOPHON
       This  page  is  part  of  release 3.15 of the Linux man-pages project.  A description of the project, and information about
       reporting bugs, can be found at http://www.kernel.org/doc/man-pages/.



4.推荐阅读

1.getrlimit和setrlimit函数

http://bbs.chinaunix.net/thread-1940558-1-1.html


<think>我们讨论的是在Linux环境下使用getrlimitsetrlimit系统调用来获取和设置资源限制,特别是栈资源限制(如设置为12MB)以及CPU资源限制。这些函数允许我们查询和修改进程的资源限制。 ### 1. 基本概念 - `getrlimit` 和 `setrlimit` 是用于获取和设置进程资源限制的系统调用。 - 每个资源都有两个限制值:当前软限制(soft limit)和最大硬限制(hard limit)。 - 软限制是内核实际执行的限制,进程可以将其增加到最大硬限制值。非特权进程只能降低硬限制,不能提高硬限制。 - 资源类型通过`resource`参数指定,常见的资源类型有: - `RLIMIT_STACK`:进程栈的最大大小(单位:字节)。如果超过这个限制,将收到`SIGSEGV`信号。 - `RLIMIT_CPU`:进程使用CPU的最大时间(单位:秒)。如果超过,将收到`SIGXCPU`信号。 ### 2. 函数原型 ```c #include <sys/resource.h> int getrlimit(int resource, struct rlimit *rlim); int setrlimit(int resource, const struct rlimit *rlim); ``` 其中,`struct rlimit`定义如下: ```c struct rlimit { rlim_t rlim_cur; /* 当前软限制 */ rlim_t rlim_max; /* 最大硬限制 */ }; ``` ### 3. 设置栈资源限制为12MB 栈资源限制由`RLIMIT_STACK`指定。12MB等于12 * 1024 * 1024字节。 示例代码: ```c #include <sys/resource.h> #include <stdio.h> #include <stdlib.h> int main() { struct rlimit rlim; // 获取当前的栈限制 if (getrlimit(RLIMIT_STACK, &rlim) == -1) { perror("getrlimit"); exit(1); } printf("当前栈限制: soft = %ld, hard = %ld (字节)\n", (long)rlim.rlim_cur, (long)rlim.rlim_max); // 设置新的栈限制:软限制为12MB,硬限制不变(保持原硬限制) rlim_t new_stack_size = 12 * 1024 * 1024; // 12MB if (new_stack_size > rlim.rlim_max) { // 如果新限制大于硬限制,且我们有权限,可以尝试提高硬限制 // 但非特权进程通常不能提高硬限制 printf("新限制超过硬限制,无法设置\n"); exit(1); } rlim.rlim_cur = new_stack_size; if (setrlimit(RLIMIT_STACK, &rlim) == -1) { perror("setrlimit"); exit(1); } printf("已设置栈软限制为 %ld 字节\n", (long)new_stack_size); return 0; } ``` ### 4. 获取CPU资源限额 CPU资源限制由`RLIMIT_CPU`指定,单位是秒。 示例代码(获取CPU限制): ```c #include <sys/resource.h> #include <stdio.h> #include <stdlib.h> int main() { struct rlimit rlim; if (getrlimit(RLIMIT_CPU, &rlim) == -1) { perror("getrlimit"); exit(1); } printf("CPU时间限制: soft = %ld 秒, hard = %ld 秒\n", (long)rlim.rlim_cur, (long)rlim.rlim_max); return 0; } ``` ### 5. 设置CPU资源限制 设置CPU资源限制与设置栈限制类似,但注意单位是秒。 ```c // 设置CPU软限制为60秒(1分钟),硬限制保持原样 rlim_t new_cpu_limit = 60; if (getrlimit(RLIMIT_CPU, &rlim) == -1) { perror("getrlimit"); exit(1); } // 保存原来的硬限制 rlim_t old_hard = rlim.rlim_max; // 设置软限制 rlim.rlim_cur = new_cpu_limit; // 如果新的软限制大于硬限制,且我们需要调整硬限制,则先调整硬限制(但非特权进程可能无法提高硬限制) // 这里我们不改变硬限制,所以确保软限制不超过硬限制 if (rlim.rlim_cur > rlim.rlim_max) { // 如果新软限制大于硬限制,且进程有权限,可以尝试提高硬限制 // 但通常非特权进程不能提高硬限制,所以这里我们只将软限制设置为硬限制的值 rlim.rlim_cur = rlim.rlim_max; } if (setrlimit(RLIMIT_CPU, &rlim) == -1) { perror("setrlimit"); exit(1); } ``` ### 6. 注意事项 - 非特权进程(非root)只能将硬限制降低,不能提高。也就是说,如果当前硬限制是X,那么软限制可以设置为0到X之间的值,而硬限制只能降低(且降低后不能提高)。 - 设置资源限制可能会影响进程的行为,例如设置栈大小过小可能导致栈溢出。 - 设置CPU限制后,当进程使用的CPU时间超过软限制时,系统会向进程发送`SIGXCPU`信号,默认行为是终止进程。但进程可以捕获这个信号并做清理工作。 ### 7. 完整示例:设置栈限制和获取CPU限制 ```c #include <sys/resource.h> #include <stdio.h> #include <stdlib.h> int main() { struct rlimit rlim; // 设置栈限制为12MB rlim_t new_stack = 12 * 1024 * 1024; if (getrlimit(RLIMIT_STACK, &rlim) == -1) { perror("getrlimit stack"); exit(1); } if (new_stack <= rlim.rlim_max) { rlim.rlim_cur = new_stack; if (setrlimit(RLIMIT_STACK, &rlim) == -1) { perror("setrlimit stack"); } else { printf("栈限制设置成功:%ld 字节\n", (long)new_stack); } } else { printf("无法设置栈限制:请求大小超过硬限制\n"); } // 获取CPU限制 if (getrlimit(RLIMIT_CPU, &rlim) == -1) { perror("getrlimit cpu"); } else { printf("CPU时间限制:软限制=%ld秒,硬限制=%ld秒\n", (long)rlim.rlim_cur, (long)rlim.rlim_max); } return 0; } ``` ### 8. 编译和运行 使用gcc编译: ```bash gcc rlimit_example.c -o rlimit_example ./rlimit_example ``` ### 相关问题 1. 如何设置进程的最大文件描述符数量? 2. 如何获取和设置进程的数据段大小(例如堆内存)? 3. 资源限制在进程间是如何继承的? 4. 如何通过shell命令(ulimit)设置栈和CPU限制? 5. 在守护进程中设置资源限制的最佳实践是什么?</think>### 使用 getrlimitsetrlimit 管理资源限制 在 Linux 系统中,`getrlimit` 和 `setrlimit` 系统调用用于获取和设置进程的资源限制。以下是获取/设置栈资源限制(如 12MB)和 CPU 资源限额的详细方法: #### 1. 资源限制结构体 ```c #include <sys/resource.h> struct rlimit { rlim_t rlim_cur; // 当前软限制(实际生效值) rlim_t rlim_max; // 最大硬限制(不可超过的值) }; ``` #### 2. 获取和设置栈资源限制(12MB) ```c #include <sys/resource.h> #include <stdio.h> int main() { struct rlimit rlim; // 获取当前栈限制 if (getrlimit(RLIMIT_STACK, &rlim) == -1) { perror("getrlimit failed"); return 1; } printf("当前栈限制: soft=%ldMB, hard=%ldMB\n", rlim.rlim_cur/(1024*1024), rlim.rlim_max/(1024*1024)); // 设置新栈限制为12MB rlim.rlim_cur = 12 * 1024 * 1024; // 12MB if (setrlimit(RLIMIT_STACK, &rlim) == -1) { perror("setrlimit failed"); return 1; } printf("已设置栈限制为12MB\n"); return 0; } ``` #### 3. 获取 CPU 资源限额 ```c #include <sys/resource.h> #include <stdio.h> int main() { struct rlimit rlim; // 获取CPU时间限制 if (getrlimit(RLIMIT_CPU, &rlim) == -1) { perror("getrlimit failed"); return 1; } if (rlim.rlim_cur == RLIM_INFINITY) { printf("CPU时间限制: 无限制\n"); } else { printf("CPU时间限制: %ld秒\n", rlim.rlim_cur); } return 0; } ``` #### 4. 关键参数说明 | 资源类型 | 宏定义 | 单位 | 说明 | |-------------------|-------------------|------------|-------------------------------| | 栈大小 | `RLIMIT_STACK` | 字节 | 进程栈的最大尺寸 | | CPU时间 | `RLIMIT_CPU` | 秒 | 进程可使用的CPU时间 | | 虚拟内存 | `RLIMIT_AS` | 字节 | 进程地址空间总大小 | | 文件大小 | `RLIMIT_FSIZE` | 字节 | 可创建文件的最大尺寸 | #### 5. 重要注意事项 1. **权限要求**: - 非特权进程只能降低硬限制,不能提高 - 只有特权进程(root)可以提高硬限制 2. **特殊值**: - `RLIM_INFINITY` 表示无限制 - 栈限制最小值通常为 128KB-256KB 3. **错误处理**: - 函数返回 -1 表示失败,检查 `errno`: - `EPERM`: 权限不足 - `EINVAL`: 无效参数 - `EFAULT`: 地址错误 4. **栈限制实际效果**: $$ \text{实际栈大小} = \min(\text{RLIMIT\_STACK}, \text{编译时指定的栈大小}) $$ 程序链接时可通过 `-z stack-size` 指定栈大小[^1] #### 6. 编译和执行 ```bash # 编译 gcc resource_limit.c -o rlimit_test # 执行 ./rlimit_test ``` #### 7. 系统级监控 查看当前进程限制: ```bash cat /proc/$$/limits # $$ 表示当前shell进程ID ``` 示例输出: ``` Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max stack size 8192 unlimited bytes ``` ### 相关问题 1. 如何设置进程的最大内存使用量? 2. 资源限制在子进程中是如何继承的? 3. 如何通过编程方式获取当前进程的资源使用统计? 4. `RLIMIT_NPROC` 和 `RLIMIT_NOFILE` 分别控制什么资源? 5. 在守护进程中设置资源限制的最佳实践是什么? 6. 如何避免因资源限制导致的程序崩溃? [^1]: Linux 手册页 `man 2 getrlimit` [^2]: 《UNIX环境高级编程》第7章 进程环境
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值