在Linux下的进程资源的限制(struct rlimit)详解

在Linux下的进程资源的限制(struct rlimit)详解

在Linux系统中,Resouce limit指在一个进程的执行过程中,它所能得到的资源的限制,比如进程的core file的最大值,虚拟内存的最大值等。

Resouce limit的大小可以直接影响进程的执行状况。其有两个最重要的概念:soft limit 和 hard limit。

struct rlimit {
rlim_t rlim_cur;
rlim_t rlim_max;
};
soft limit是指内核所能支持的资源上限。比如对于RLIMIT_NOFILE(一个进程能打开的最大文件 数,内核默认是1024),soft limit最大也只能达到1024。对于RLIMIT_CORE(core文件的大小,内核不做限制),soft limit最大能是unlimited。
hard limit在资源中只是作为soft limit的上限。当你设置hard limit后,你以后设置的soft limit只能小于hard limit。要说明的是,hard limit只针对非特权进程,也就是进程的有效用户ID(effective user ID)不是0的进程。具有特权级别的进程(具有属性CAP_SYS_RESOURCE),soft limit则只有内核上限。

我们可以来看一下下面两条命令的输出。

sishen@sishen:~$ ulimit -c -n -s
core file size (blocks, -c) 0
open files (-n) 1024
stack size (kbytes, -s) 8192
sishen@sishen:~$ ulimit -c -n -s -H
core file size (blocks, -c) unlimited
open files (-n) 1024
stack size (kbytes, -s) unlimited

-H表示显示的是hard limit。从结果上可以看出soft limit和hard limit的区别。unlimited表示no limit, 即内核的最大值。
对于resouce limit的读取修改,有两种方法。


使用shell内建命令ulimit 
使用getrlimit和setrlimit API 

ulimit是改变shell的resouce limit,并达到改变shell启动的进程的resouce limit效果(子进程继承)。
usage:ulimit [-SHacdefilmnpqrstuvx [limit]]
当不指定limit的时候,该命令显示当前值。这里要注意的是,当你要修改limit的时候,如果不指定-S或者-H,默认是同时设置soft limit和hard limit。也就是之后设置时只能减不能增。所以,建议使用ulimit设置limit参数是加上-S。
getrlimit和setrlimit的使用也很简单,manpage里有很清楚的描述。
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
需要注意的是你在setrlimit,需要检查是否成功来判断新值有没有超过hard limit。如下例:
if (getrlimit(RLIMIT_CORE, &rlim)==0) {
rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &rlim_new)!=0) {
rlim_new.rlim_cur = rlim_new.rlim_max =
rlim.rlim_max;
(void) setrlimit(RLIMIT_CORE, &rlim_new);
}
}

 

setrligetrlimit和setrlimit函数
2008-07-03 17:20


 每个进程都有一组资源限制,其中某一些可以用getrlimit和setrlimit函数查询和更改。


#include 
#include 
int getrlimit(int resource,struct rlimit *rlptr);
int setrlimit(int resource,const struct rlimit rlptr);
Both return: 0 if OK,nonzero on error两个函数


  返回:若成功为0,出错为非0

  对这两个函数的每一次调用都指定一个资源以及一个指向下列结构的指针。


struct rlimit{
rlim rlim ur;/* 软限制:当前限制 */
rlim rlim ax;/* 硬限制:rlimcur的最大值 */
};


  这两个函数不属于POSIX.1,但SVR4和4.3+BSD提供它们。SVR4在上面的结构中使用基本系统数据类型rlim。其它系统则将这两个成员定义为整型或长整型。

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

  在更改资源限制时,须遵循下列三条规则:

  1.任何一个进程都可将一个软限制更改为小于或等于其硬限制。
2.任何一个进程都可降低其硬限制值,但它必须大于或等于其软限制值。这种降低,对普通用户而言是不可逆反的。
3.只有超级用户可以提高硬限制。

  一个无限量的限制由常数RLIM NFINITY指定。

  这两个函数的resource参数取下列值之一。注意并非所有资源限制都受到SVR4和4.3+BSD的支持。

  RLMITCORE(SVR4及4.3+BSD)core文件的最大字节数,若其值为0则阻止创建core文件。
RLIMIT PU(SVR4及4.3+BSD)CPU时间的最大量值(秒),当超过此软限止时,向该进程发送SIGXCPU信号。
RLIMIT ATA(SVR4及4.3+BSD)数据段的最大字节长度。这是图7.3中初始化数据、非初始化数据以及堆的总和。
RLIMIT SIZE(SVR4及4.3+BSD)可以创建的一个文件的最大字节长度。当超过此软限制时,则向该进程发送SIGFSZ信号。
RLIMIT EMLOCK(4.3+BSD)锁定在存储器地址空间(尚末实现)。
RLIMIT OFILE(SVR4)每个进程最多打开的文件数。更改此限制将影响到sysconf函数在参数-sc-OPEN-MAX中返回的值(2.5.4节)。见程序2.3。
RLIMIT PROC(4.3+BSD)每个实际用户ID所拥有的最大子进程数。更改此限制将影响到sysconf函数在参数 CHILDMAX中返回的值(2.5.4节)。
RLIMIT FILE(4.3+BSD)与SVR4的RLIMIT OFILE相同。
RLIMIT SS(4.3+BSD)最大驻内存集字节长度(RSS)。如果物理存储器供子应求,则系统核将从进程处取回超过RSS的部分。
RLIMIT TACK(SVR4及4.3+BSD)栈的最大字节长度。见图7.3。
RLIMIT MEM(SVR4)可映照地址空间的最大字节长度。这影响到mmap函数(12.9节)。

  资源限制影响到调用进程并由其子进程继承。这就意味着为了影响一个用户的所有后续进程,需将资源限制 设置构造在shell之中。确实,Bourne Shell和Kornshell具有内部ulimit命令,CShell具有内部limit命令。(umask和chdir也必须是shell内部的)。

  较早的BourmeShell,例如由贝克莱提供的一种,不支持ulimit命令。较新的KornShell的ulimit命令具有-H和-s选择项,以分别检查和修改硬和软的限制,但它们尚末编写入文档。

简单的用例:

#include<sys/time.h>
#include<sys/resource.h>
#include<unistd.h>
int main()
{
        struct rlimit limit;
        char p = '1';
        limit.rlim_cur = RLIM_INFINITY;
        limit.rlim_max = RLIM_INFINITY;
        if(setrlimit(RLIMIT_CORE, &limit))
        {
                printf("set limit failed\n");
        }

        printf("p = %s\n",p);

面列表为unix/linux 系统单进程资源参数限制,服务器开发中 RLIMIT_CORE 参数用得多(当需要产生core dump时)。

 

代码片段:

 

[cpp]  view plain copy
  1.               memset(&limit, 0, sizeof(limit));  
  2.     limit.rlim_cur = RLIM_INFINITY;  
  3.     limit.rlim_max = RLIM_INFINITY;  
  4.     if(setrlimit(RLIMIT_CORE, &limit)) {  
  5.     spd_log(LOG_WARNING, " unable to disable core size res limit %s\n", strerror(errno));  
  6.     }  
  7.   
  8.     if(getrlimit(RLIMIT_CORE, &limit)) {  
  9.     spd_log(LOG_WARNING, "unable to check rlimit of fd%s\n", strerror(errno));  
  10. }  


 

 

 

名称 意义
RLIMIT_AS 进程总共可用的内存大小的最大值
RLIMIT_CORE core文件的最大尺寸,如果为0说明不能创建core文件
RLIMIT_CPU CPU时间的最大值(单位:秒)
RLIMIT_DATA 数据段大小的最大值
RLIMIT_FSIZE 创建文件的大小的最大值
RLIMIT_LOCKS 进程可建立的文件锁的数量的最大值
RLIMIT_MEMLOCK 进程中使用mlock锁定内存的最大尺寸
RLIMIT_NOFILE 进程中文件的打开数量的最大值
RLIMIT_NPROC 每个real user id的子进程数量的最大值
RLIMIT_RSS 最大常驻存储区大小
RLIMIT_SBSIZE socket缓冲的大小的最大值
RLIMIT_STACK 栈的最大尺寸
RLIMIT_VMEM =RLIMIT_AS

 

 

平台支持

 


限制

FreeBSD 5.2.1

Linux 2.4.22 Mac OS X 10.3 Solaris 9
RLIMIT_AS N   N  
RLIMIT_CORE        
RLIMIT_CPU        
RLIMIT_DATA        
RLIMIT_FSIZE        
RLIMIT_LOCKS N   N N
RLIMIT_MEMLOCK       N
RLIMIT_NOFILE        
RLIMIT_NPROC       N
RLIMIT_RSS       N
RLIMIT_SBSIZE   N N N
RLIMIT_STACK        
RLIMIT_VMEM   N N

ulimit命令优化linux进程连接数等限

在Linux下面部署应用的时候,有时候会遇上Socket/File: Can’t open so many files的问题,比如还有Squid做代理,当文件打开数到900多时速能就非常快的下降,有可能打不开网页.其实Linux是有文件句柄限制的,而且Linux默认不是很高,一般都是1024,生产服务器用其实很容易就达到这个数量.

[root@mail data]# ulimit -a
core file size           (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 66560
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                       (-n) 8192
pipe size             (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority               (-r) 0
stack size               (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes               (-u) 66560
virtual memory           (kbytes, -v) unlimited
file locks                       (-x) unlimited
[separator]
     其中 “open files (-n) 1024 “是Linux操作系统对一个进程打开的文件句柄数量的限制(也包含打开的SOCKET数量,可影响MySQL的并发连接数目).这个值可用ulimit 命令来修改,但ulimit命令修改的数值只对当前登录用户的目前使用环境有效,系统重启或者用户退出后就会失效.
     系统总限制是在这里,/proc/sys/fs/file-max.可以通过cat查看目前的值,修改/etc/sysctl.conf 中也可以控制.
     另外还有一个,/proc/sys/fs/file-nr,可以看到整个系统目前使用的文件句柄数量
     查找文件句柄问题的时候,还有一个很实用的程序lsof.可以很方便看到某个进程开了那些句柄.也可以看到某个文件/目录被什么进程占用了
[root@kyouwar data0]# cat /proc/sys/fs/file-max
372901
[root@kyouwar data0]# cat /proc/sys/fs/file-nr 
3200     0       372901
=====================================
ulimit 用于shell启动进程所占用的资源。
可以使用该命令查看进程占用资源的情况。
使用方法:ulimit [-acdfHlmnpsStvw] [size]
-H 设置硬件资源限制.
-S 设置软件资源限制.
-a 显示当前所有的资源限制.
-c size:设置core文件的最大值.单位:blocks
-d size:设置数据段的最大值.单位:kbytes 
     ulimit -d unlimited 
-f size:设置创建文件的最大值.单位:blocks
-l size:设置在内存中锁定进程的最大值.单位:kbytes
-m size:设置可以使用的常驻内存的最大值.单位:kbytes
     ulimit -m unlimited
-n size:设置内核可以同时打开的文件描述符的最大值【每个进程可以打开的文件数目】【也包含打开的SOCKET数量,可影响MySQL的并发连接数目】.单位:n
-p size:设置管道缓冲区的最大值.单位:kbytes
-s size:设置堆栈的最大值.单位:kbytes
     ulimit -s unlimited
-t size:设置CPU使用时间的最大上限.单位:seconds
     ulimit -t unlimited 
-v size:设置虚拟内存的最大值.单位:kbytes 5
-u 设置各linux 用户的最大进程数
     ulimit -u 10000 
============================================
#暂时修改直接使用
     ulimit -参数 xx
如:
   同时修改软硬设置   ulimit -SHn 4500
----------------------------------------------------
# 永久地,通过将一个相应的 ulimit 语句添加到由登录 shell 读取的文件中, 即特定于 shell 的用户资源文件,如
1)、解除 Linux 系统的最大进程数和最大文件打开数限制:
vi /etc/security/limits.conf
# 添加如下的行
* soft noproc 11000
* hard noproc 11000
* soft nofile 8192
* hard nofile 8192
#如此每次用户登录后就依照此值设置。

说明:* 代表针对所有用户
noproc 是代表最大进程数
nofile 是代表最大文件打开数
     可以将文件句柄限制统一改成软11000,硬11000.配置文件最前面的是指domain,设置为星号代表全局,另外你也可以针对不同的用户做出不同的限制
     注意.这个当中的硬限制是实际的限制,而软限制,是warnning限制,只会做出warning.其实ulimit命令本身就有分软硬设置,加-H就是硬,加-S就是软
     默认显示的是软限制,如果运行ulimit命令修改的时候没有加上的话,就是两个参数一起改变.
============================================
2)、让 SSH 接受 Login 程式的登入,方便在 ssh 客户端查看 ulimit -a 资源限制:
         a、vi /etc/ssh/sshd_config 
             把 UserLogin 的值改为 yes,并把 # 注释去掉
         b、重启 sshd 服务:
               /etc/init.d/sshd restart
#新版本好像不用设置这个!也没有这个配置选项
============================================
3)、修改所有 linux 用户的环境变量文件:
vi /etc/profile
ulimit -u 10000
ulimit -n 4096
ulimit -d unlimited
ulimit -m unlimited
ulimit -s unlimited
ulimit -t unlimited
ulimit -v unlimited
============================================
4)、生效
     修改完重新登录就可以见到.可以用ulimit -a 查看确认.)
----------------------------------------------------
     注意:如果你使用squid的话,你要在/etc/init.d/squid的文件加入ulimit -HSn 65535.另外,在squid.conf中也要加入max_filedesc 16384
============================================
特殊说明:
   注:上面这种方式只是改变了用户登陆系统后的文件打开数,对于/etc/init.d /nginx这种的启动脚本并不起作用,像这种启动脚本,需要在脚本内 程序命令前加一行:
   ulimit -HSn 65535
============================================
补充:可不设置
     生产服务器的配置说明
     有时候在程序里面需要打开多个文件,进行分析,系统一般默认数量是1024,(用ulimit -a可以看到)对于正常使用是够了,但是对于程序来讲,就太少了。
修改2个文件。
1./etc/security/limits.conf
vi /etc/security/limits.conf
加上:
* soft nofile 8192
* hard nofile 20480
----------------------------------------------------
2./etc/pam.d/login
session required /lib/security/pam_limits.so
   另外确保/etc/pam.d/system-auth文件有下面内容
session required /lib/security/$ISA/pam_limits.so
   这一行确保系统会执行这个限制。
----------------------------------------------------
3.一般用户的.bash_profile
#ulimit -n 1024
重新登陆ok




你可能感兴趣的:(在Linux下的进程资源的限制(struct rlimit)详解)