setrlimit()&getrlimit()设置和获取Linux下进程可用资源

本文介绍Linux系统中getrlimit和setrlimit两个API的功能及使用方法,包括如何获取和设置进程资源限制,如CPU时间、内存大小等,并通过示例代码展示具体的实现过程。

本文根据MSDA和百度空间的文章整理,向作者致谢。

参考文章链接

http://hi.baidu.com/phps/blog/item/7e3ba44410cf9580b3b7dc81.html
http://blog.youkuaiyun.com/msda/article/details/4463688

 getrlimit && setrlimit

一个进程都有自己的一组资源限制,在Linux系统中我们可以通过 getrlimit()/setrlimit()这2个API来取得和设置资源:

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

Both return: 0 if OK,nonzero on error

getrlimit用来取得setrlimit用来设置.

第一个参数表示要控制的资源,比如控制CPU、内存、文件描述符个数等等的控制,第二个参数是一个rlimit的结构体地址(指针),它的结构如下定义:
定义放在头文件/usr/include/bits/resource.h中
struct rlimit
       {
         /* The current (soft) limit.       */
         rlim_t rlim_cur;
         /* The hard limit.       */
         rlim_t rlim_max;
       };
结构体中 rlim_cur是要取得或设置的资源软限制的值,rlim_max是硬限制。

这两个值的设置有一个小的约束:
1) 任何进程可以将软限制改为小于或等于硬限制
2) 任何进程都可以将硬限制降低,但普通用户降低了就无法提高,该值必须等于或大于软限制
3) 只有超级用户可以提高硬限制

注意:
1.两个函数不属于POSIX.1,但SVR4和4.3+BSD提供它们。注意,并非所有资源限制都受到SVR4和4.3+BSD的支持。==>what's SVR4????
SVR4在上面的结构中使用基本系统数据类型rlim。其它系统则将这两个成员定义为整型或长整型。

2.进程的资源限制通常是在系统初启时由0#进程建立的,然后由后续进程继承。在SVR4中,系统默认值可以查看文件/etc/conf/cfd/mtune ==> need to verification
在4.3+BSD中,系统默认值分散在多个头文件中。

3.资源限制影响到调用进程并由其子进程继承。这就意味着为了影响一个用户的所有后续进程,需将资源限制设置构造在shell之中。确实,Bourne Shell和Kornshell具有内部ulimit命令,CShell具有内部limit命令。(umask和chdir也必须是shell内部的)。较早的BourmeShell,例如由贝克莱提供的一种,不支持ulimit命令。较新的KornShell的ulimit命令具有-H和-s选择项,以分别检查和修改硬和软的限制,但它们尚末编写入文档。

这两个函数的resource参数取下列值之一。
一个无限的限制由常量RLIM_INFINITY指定(The value RLIM_INFINITY denotes no limit on a resource )

RLIMIT_AS
The maximum size of the process鈙 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 when no alternate stack has been made available). 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 ==》bytes or blocks??A:对于此函数来说,单位应该是Byte,但是当调用ulimit查看或者设置core_file的大小时,单位为blocks.
Maximum size of core file. When 0 no core dump files are created. When nonzero, larger dumps are truncated to this size.
设定最大的core文件,当值为0时将禁止core文件非0时将设定产生的最大core文件大小为设定的值

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 and 2.4 behaviour. Implementations vary in how they treat processes which continue to consume CPU time after reaching the soft limit. Portable applications that needto catch this signal should perform an orderly termination upon first receipt of SIGXCPU.)
CPU时间的最大量值(秒),当超过此软限制时向该进程发送SIGXCPU信号

RLIMIT_DATA
                   The maximum size of the       process     data       segment       (initialized
                   data,       uninitialized data, and heap).       This limit affects calls
                   to brk() and sbrk(), 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       delivery
                   of a SIGXFSZ signal.       By default, this signal terminates a pro-
                   cess, but a process can catch this       signal       instead,       in       which
                   case the relevant system call (e.g., write(), truncate()) fails
                   with the error EFBIG.
可以创建的文件的最大字节长度,当超过此软限制时向进程发送SIGXFSZ
RLIMIT_MEMLOCK
                   The maximum number of bytes       of       virtual       memory       that       may       be
                   locked into RAM using mlock() and mlockall().
RLIMIT_NOFILE
                   Specifies       a value one greater than the maximum file descriptor
                   number that can be opened by this process.        Attempts       (open(),
                   pipe(),       dup(),       etc.)        to       exceed       this limit yield the error
                   EMFILE.
每个进程能够打开的最多文件数。更改此限制将影响到sysconf函数在参数_SC_CHILD_MAX中的返回值
RLIMIT_OFILE is the BSD name for RLIMIT_NOFILE.
这里BSD系统中RLIMIT_NOFILE的别名
RLIMIT_NPROC
                   The maximum number of processes that can       be       created       for       the
                   real       user       ID       of the calling process.       Upon encountering this
                   limit, fork() fails with the error EAGAIN.
每个实际用户ID所拥有的最大子进程数,更改此限制将影响到sysconf函数在参数_SC_CHILD_MAX中返回的值
RLIMIT_RSS
                   Specifies the limit (in pages) of the       process鈙       resident       set
                   (the number of virtual pages resident in RAM).       This limit only
                   has effect in Linux 2.4 onwatrds, and there only affects       calls
                   to madvise() specifying MADVISE_WILLNEED.
最大驻内存集字节长度(RSS)如果物理存储器供不应求则内核将从进程处取回超过RSS的部份
RLIMIT_STACK
                   The maximum size of the process stack, in bytes.       Upon reaching
                   this limit, a SIGSEGV signal is generated.       To handle this sig-
                   nal,       a       process must employ an alternate signal stack (sigalt-
                   stack(2)).
栈的最大长度
RLIMIT——VMEM 可映照地址空间的最大字节长茺,这影响到mmap函数
这些限制影响到调用进程并由子进程继承! 可以在SHELL中预设这些值ulimit命令设置

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/resource.h>
int main(void)
{
     struct rlimit r;
     if(getrlimit(RLIMIT_NOFILE,&r)<0)
     {
         fprintf(stderr,"getrlimit error\n");
         exit(1);
     }
     printf("RLIMIT_NOFILE cur:%d\n",r.rlim_cur);
     printf("RLIMIT_NOFILE max:%d\n",r.rlim_max);

     /** set limit **/
     r.rlim_cur=100;
     r.rlim_max=200;
     if (setrlimit(RLIMIT_NOFILE,&r)<0)
     {
         fprintf(stderr,"setrlimit error\n")
         exit(1);
     }

     /** get value of set **/
     if(getrlimit(RLIMIT_NOFILE,&r)<0)
     {
         fprintf(stderr,"getrlimit error\n");
         exit(1);
     }
     printf("RLIMIT_NOFILE cur:%d\n",r.rlim_cur);
     printf("RLIMIT_NOFILE max:%d\n",r.rlim_max);
     return 0;
}

<think> 根据用户需求,我们需要在Linux系统中使用C代码获取可用最大线程数。在Linux系统中,线程是轻量级进程(LWP),因此我们可以通过系统限制来获取最大线程数。通常,我们可以通过系统调用`sysconf`或者读取`/proc/sys/kernel/threads-max`文件来获取系统级别的最大线程数。此外,每个进程也有自己的最大线程数限制,可以通过`getrlimit`函数设置获取。 步骤: 1. 系统级别的最大线程数:可以通过读取`/proc/sys/kernel/threads-max`文件得到。 2. 进程级别的最大线程数:使用`getrlimit`函数获取当前进程可创建线程数的限制(RLIMIT_NPROC),但注意这个限制是用户级别的进程数(包括线程)限制。实际上,在Linux中,线程是通过进程实现的(每个线程都是一个轻量级进程),所以线程数也受此限制。 然而,需要注意的是,每个线程还会消耗其他资源(如栈空间),因此实际可创建的线程数还可能受到栈大小限制(RLIMIT_STACK)虚拟内存大小限制(RLIMIT_AS)等的影响。 因此,我们可以采取以下方法之一: 方法1:读取`/proc/sys/kernel/threads-max`文件,获取系统允许的最大线程数。 方法2:使用`getrlimit`获取RLIMIT_NPROC的软限制硬限制,这表示当前用户可创建的进程(线程)的最大数量。 但是,用户可能需要的是当前进程还能创建多少线程,这需要考虑已经创建的线程数。所以,我们可以结合`getrlimit`当前已经创建的线程数来计算。 不过,用户的问题只是“获取可用最大线程数”,通常指的是系统或者当前用户允许的最大线程数。这里我们提供两种方式: 1. 获取系统全局最大线程数(从`/proc/sys/kernel/threads-max`读取) 2. 获取当前进程的最大线程数限制(使用`getrlimit`的RLIMIT_NPROC,但要注意这个限制是用户级别的,所以同一个用户的所有进程共享这个限制) 另外,每个线程都需要独立的栈空间,所以栈空间的大小也会影响实际可创建的线程数。我们可以通过`pthread_attr_getstacksize`获取默认栈大小,然后根据剩余虚拟地址空间来计算,但这种方法比较复杂且不常用。 通常,我们更关心系统或用户级别的限制。 下面,我们分别用代码实现这两种方法: 方法1:读取/proc/sys/kernel/threads-max 方法2:使用getrlimit获取RLIMIT_NPROC 注意:方法2得到的限制是当前用户可创建的进程(线程)总数。如果当前用户已经创建了很多进程(线程),那么当前进程可创建的线程数就会相应减少。 因此,要精确计算当前进程还能创建多少线程,需要知道当前用户已经创建的进程(线程)数。我们可以通过遍历`/proc`文件系统来统计,但这比较复杂,而且通常我们只需要知道上限。 根据用户需求,我们提供两种最大线程数的获取方法,并给出代码示例。 另外,需要注意的是,在Linux中,线程创建还受到内存等资源的限制,所以实际可创建的线程数可能小于这些限制值。 代码示例: 我们将编写一个程序,分别输出: 1. 系统全局最大线程数(从/proc读取) 2. 当前用户可创建的最大进程(线程)数(使用getrlimit的RLIMIT_NPROC) 同时,我们也可以考虑线程栈大小对线程数的影响,但这里不计算具体值,只提醒用户注意。 下面是代码: ```c #include <stdio.h> #include <stdlib.h> #include <sys/resource.h> int main() { FILE *fp; long max_threads_system = 0; // 方法1:读取/proc/sys/kernel/threads-max fp = fopen("/proc/sys/kernel/threads-max", "r"); if (fp) { fscanf(fp, "%ld", &max_threads_system); fclose(fp); printf("System-wide maximum number of threads: %ld\n", max_threads_system); } else { perror("Failed to open /proc/sys/kernel/threads-max"); } // 方法2:使用getrlimit获取RLIMIT_NPROC(用户级别的最大进程数,包括线程) struct rlimit rlim; if (getrlimit(RLIMIT_NPROC, &rlim) == 0) { printf("Current user maximum number of processes (including threads): soft limit = %ld, hard limit = %ld\n", (long)rlim.rlim_cur, (long)rlim.rlim_max); } else { perror("getrlimit failed"); } return 0; } ``` 注意:RLIMIT_NPROC限制的是同一个用户ID下可创建的进程(线程)总数。所以,如果当前用户已经运行了很多进程,那么即使这个限制很大,也可能无法创建新的线程。 另外,还有一个限制是每个进程的最大线程数,这个限制是由内核参数`/proc/sys/kernel/pid_max`决定的(因为每个线程都有一个唯一的PID,所以线程数不可能超过pid_max)。但是,实际上,线程数通常不会达到pid_max,因为还有其他资源限制。 因此,我们通常关注上面两种方法即可。 如果用户需要更精确的可用线程数(即当前还能创建多少线程),那么需要减去当前已经存在的线程数。但是,获取当前用户已经创建的进程(线程)总数需要遍历/proc,这比较麻烦,而且通常只有root用户才有权限读取所有进程信息。 所以,我们这里只提供最大限制的获取方法。 总结: 在Linux系统中,获取可用最大线程数的方法主要有两种: 1. 系统全局最大线程数:读取`/proc/sys/kernel/threads-max` 2. 当前用户可创建的最大进程(线程)数:使用`getrlimit(RLIMIT_NPROC)` 我们根据用户需求,提供了C代码示例。 注意:这两个值都是理论上的最大值,实际可创建的线程数可能受其他因素(如内存、栈大小等)的影响而减小。 另外,在编写多线程程序时,应当合理设计,避免创建过多的线程。 </think> 在Linux系统中,可以通过C代码获取系统允许的最大线程数。以下是两种常用方法: ### 方法1:读取系统参数文件 直接读取内核参数文件`/proc/sys/kernel/threads-max`,该文件包含系统级别的最大线程数限制: ```c #include <stdio.h> int main() { FILE *fp; long max_threads; fp = fopen("/proc/sys/kernel/threads-max", "r"); if (fp == NULL) { perror("Failed to open file"); return 1; } if (fscanf(fp, "%ld", &max_threads) != 1) { perror("Failed to read value"); fclose(fp); return 1; } fclose(fp); printf("System-wide max threads: %ld\n", max_threads); return 0; } ``` ### 方法2:使用`sysconf`系统调用 通过`sysconf`函数获取进程级别的最大线程数限制: ```c #include <stdio.h> #include <unistd.h> int main() { long max_threads = sysconf(_SC_THREAD_THREADS_MAX); if (max_threads == -1) { perror("sysconf failed"); return 1; } printf("Process max threads: %ld\n", max_threads); return 0; } ``` ### 关键说明: 1. **系统级限制** `/proc/sys/kernel/threads-max`给出整个系统的最大线程数限制,可通过命令查看: ```bash cat /proc/sys/kernel/threads-max ``` 2. **进程级限制** `sysconf(_SC_THREAD_THREADS_MAX)`返回当前进程可创建的最大线程数,实际值受以下因素影响: - 用户级限制 (`ulimit -u`) - 内存资源(特别是线程栈大小) - 系统内核参数 3. **实际限制因素** 即使系统允许大量线程,实际可创建数还受限于: - 栈空间大小(通过`pthread_attr_setstacksize`设置) - 虚拟内存限制(通过`setrlimit(RLIMIT_AS, ...)`配置) - 可用物理内存CPU核心数 > 建议:生产环境中通常通过`ulimit -u`调整用户级进程/线程限制,或修改`/etc/security/limits.conf`配置文件[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值