C/C++:进程资源限制函数(getrlimit、setrlimit)&& Shell-ulimit命令

C/C++:进程资源限制函数(getrlimit、setrlimit)&& Shell-ulimit命令

进程在操作系统内核中是一个独立存在的运行实体。

每个进程都有 一组 资源限制,限制进程对于系统资源的申请量。

可以通过 getrlimit 来获取当前进程某一指定资源的限制。

可以通过 setrlimit 来设置当前进程某一指定资源的限制。

进程的资源限制通常是在系统初始化时由0进程建立的,然后后续进程继承。

即:进程的资源限制,是继承自fork当前进程的那个进程—父进程。
#include <sys/time.h>
#include <sys/resource.h>

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

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

rlimit 的结构可以看出,每个进程每种资源限制分为两种:1)硬限制;2)软限制;

在设置进程的资源限制时,有三条规则:

1)进程可以将某资源的软限制值更改为小于或等于其硬限制值;

2)任何一个进程可以降低某资源的硬限制值,但必须大于等于对应资源的软限制值,且这种“降低”对于非root用户是不可逆的;

3)只有root用户进程可以提高硬限制值;

资源限制有多种,我列举下比较常用,比较关心的几类:


RLIMIT_CORE

进程core时,core文件最大字节数(单位字节),若其值为0则不创建core文件。


RLIMIT_FSIZE

每个进程可创建的文件的最大字节长度(单位字节)。


RLIMIT_NOFILE

每个进程能打开的最大文件数目。


RLIMIT_NPROC

每个实际用户ID可拥有的最大子进程数目。

Case:列出当前进程的软硬资源限制。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>

#define doit(name) limit(#name, name)

static void limit(const char *name, int resource)
{
    struct rlimit limit;
    unsigned long long value;

    if (getrlimit(resource, &limit) != 0)
    {
        printf("getrlimit %s = %d(%s)\n", name, errno, strerror(errno)); 
        return;
    }
    printf("%-16s", name);

    if (limit.rlim_cur == RLIM_INFINITY)
        printf("%-10s", "infinite");
    else
    {
        value = limit.rlim_cur;
        printf("%-10lld", value);
    }

    if (limit.rlim_max == RLIM_INFINITY)
        printf("%-10s", "infinite");
    else
    {
        value = limit.rlim_cur;
        printf("%-10lld", value);
    }

    printf("\n");
}

int main()
{

#ifdef RLIMIT_CORE
    doit(RLIMIT_CORE);
#else
    printf("RLIMIT_CORE NOT SUPPORTED\n");
#endif

#ifdef RLIMIT_FSIZE
    doit(RLIMIT_FSIZE);
#else
    printf("RLIMIT_FSIZE NOT SUPPORTED\n");
#endif

#ifdef RLIMIT_NOFILE
    doit(RLIMIT_NOFILE);
#else
    printf("RLIMIT_NOFILE NOT SUPPORTED\n");
#endif

#ifdef RLIMIT_NPROC
    doit(RLIMIT_NPROC);
#else
    printf("RLIMIT_NPROC NOT SUPPORTED\n");
#endif

#ifdef RLIMIT_VMEM
    doit(RLIMIT_VMEM);
#else
    printf("RLIMIT_VMEM NOT SUPPORTED\n");
#endif

    return 0;
}

编译 && 运行:

[jiang@localhost 0520]$ gcc -o resource resource.c
[jiang@localhost 0520]$ ./resource 
RLIMIT_CORE     1048576   1048576   
RLIMIT_FSIZE    infinite  infinite  
RLIMIT_NOFILE   4096      4096      
RLIMIT_NPROC    1024      1024      
RLIMIT_VMEM NOT SUPPORTED

通过以上输出结果,我们可以知晓进程资源限制情况。

例如,进程的core文件限制是1024*1024=1048576字节,1024KB。

Shell内部命令—ulimit

在shell中man ulimit,可以看到ulimit的功能:

Provides control over the resources available to the shell and to processes started by it.

ulimit可以提供对shell进程本身以及由shell进程fork出来的进程的资源控制。

说到这里,我倒是想先提一下,对于shell来说,我们输入的命令分类。

第一种是外部命令。

外部命令是一个可执行文件,当我们执行外部命令时,通常是这样子的:

1)shell(记为shell-father)在终端IO操作读取外部命令的名字,然后fork出一个新的shell子进程(记为shell-son);

2)shell-son也是知道外部命令的名字的,然后shell-son执行exec系统调用,执行指定的外部命令程序;

3)shell-father在 fork shell-son 后就一直waitpid或者wait(假设外部命令启动在前台),阻塞(直到wait返回);

4)shell-son进程体(或者称为外部命令执行进程更合适)执行完毕,exit退出进程(内核发SIGCHLD给shell-father);

5)shell-father在wait到刚刚fork出的shell-son进程体,从wait/waitpid阻塞中返回,然后继续在终端进行IO操作。

注:

shell-son知道要执行的外部命令的名字,是由于shell-father在fork后,这两个进程是一样样的,父进程有的数据,子进程也有完全相同的一份;

shell-son的前三个fd,是继承自shell-father的stdin、stdout、stderr。

举个栗子:

shell-son的fd=1和shell-father的fd=1指向同一个内核中的文件表(共享偏移量等),也就是指向的是同一个文件,只不过这个文件是标准输出。

所以,当shell-son在stdout输出和shell-father在stdout输出,都是到同一个文件,即同一个终端。

第二种是内部命令。

外部命令是由当前shell执行fork并在子进程中exec执行的命令。

内部命令是由当前shell直接执行,不经过fork以及exec系统调用完成的内部操作。

常见的有cd、ulimit等命令。

shell从终端输入上读取到 cd xxx 时,shell会解析xxx为一个路径,然后修改当前shell进程的内部变量值,以完成cd操作。

ulimit命令同理。

当进程读取到ulimit命令时,将解析ulimit命令后面的参数信息,然后执行setrlimit和getrlimit操作,修改当前shell的资源限制。

我们再一次回想man手册中对ulimit的描述:

Provides control over the resources available to

the shell (内部命令,当前shell进程自身

and to

processes started by it(外部命令,由当前shell fork出来的子进程,子进程的资源限制继承自当前shell进程).

下面简单介绍下shell ulimit内部命令。

ulimit [-SHacdefilmnpqrstuvx [limit]]

-H = hard

-S = soft

-a     All current limits are reported
-c     The maximum size of core files created
-f     The maximum size of files written by the shell and its children
-n     The maximum number of open file descriptors (most systems do not allow this value to be set)
-q     The maximum number of bytes in POSIX message queues
-u     The maximum number of processes available to a single user
……

Case 1:列出当前shell的资源软/硬限制

资源软限制:

[jiang@localhost ~]$ ulimit -Sa
core file size          (blocks, -c) 1024
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3810
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
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) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

资源硬限制:

[jiang@localhost ~]$ ulimit -Ha
core file size          (blocks, -c) 2048
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3810
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 4096
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) unlimited
cpu time               (seconds, -t) unlimited
max user processes              (-u) 3810
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

我们可以观察到,对于CORE文件大小,当前shell的软限制是1024,硬限制是2048。

Case 2:修改当前shell的资源软硬限制

资源硬限制:

[jiang@localhost ~]$ ulimit -Hc
2048
[jiang@localhost ~]$ ulimit -Hc 1408
[jiang@localhost ~]$ ulimit -Hc 1280
[jiang@localhost ~]$ ulimit -Hc 1152
[jiang@localhost ~]$ ulimit -Hc 1024
[jiang@localhost ~]$ ulimit -Hc 1280
-bash: ulimit: core file size: cannot modify limit: Operation not permitted

最开始,当前shell的CORE大小资源硬限制为2048,然后不断改小,设置为1408、1280、1152、1024都是可以的。

在当前shell的CORE大小资源硬限制为1024时,尝试设置其为更大的一个数值,1280,结果操作不被允许,执行失败。

硬限制只能向低的值设置,非特权用户不能提高资源硬限制值。

资源软限制:

[jiang@localhost ~]$ ulimit -Sc
1024
[jiang@localhost ~]$ ulimit -Hc
2048
[jiang@localhost ~]$ ulimit -Sc 1152
[jiang@localhost ~]$ ulimit -Sc 1280
[jiang@localhost ~]$ ulimit -Sc 1408
[jiang@localhost ~]$ ulimit -Sc
1408
[jiang@localhost ~]$ ulimit -Hc
2048

最开始当前shell的CORE资源软限制为1024,资源硬限制为2048,逐渐增大资源软限制值为1152、1280、1408。

资源软限制可以不断增大,但不能超过资源硬限制值的大小。

Case 3:资源限制在进程间的继承

Code:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>

#define doit(name) limit(#name, name)

static void limit(const char *name, int resource)
{
    struct rlimit limit;
    unsigned long long value;

    if (getrlimit(resource, &limit) != 0)
    {
        printf("getrlimit %s = %d(%s)\n", name, errno, strerror(errno)); 
        return;
    }
    printf("%-16s", name);

    if (limit.rlim_cur == RLIM_INFINITY)
        printf("%-10s", "infinite");
    else
    {
        value = limit.rlim_cur;
        printf("%-10lld", value);
    }

    if (limit.rlim_max == RLIM_INFINITY)
        printf("%-10s", "infinite");
    else
    {
        value = limit.rlim_cur;
        printf("%-10lld", value);
    }

    printf("\n");
}

int main()
{
#ifdef RLIMIT_CORE
    doit(RLIMIT_CORE);
#else
    printf("RLIMIT_CORE NOT SUPPORTED\n");
#endif
    return 0;
}

查看当前shell的CORE文件大小资源限制:

[jiang@localhost 0520]$ ulimit -Hc
2048
[jiang@localhost 0520]$ ulimit -Sc
1024

编译 && 执行上述程序:

[jiang@localhost 0520]$ gcc -o resource resource.c 
[jiang@localhost 0520]$ ./resource 
RLIMIT_CORE     1048576   1048576

在子进程中,资源软硬限制都是1024KB。

于是我猜测(注意,我没看过源码,只是实验得出的一个可能的猜测哈!):

子进程中的资源软硬限制 都是 直接继承自父进程的 软限制值 ,和父进程的 硬限制值 无关。

Case 4:修改系统配置,改变某用户对于某种资源的限制值

相关配置路径为:

/etc/security/limits.conf

[root@localhost ~]# cat /etc/security/limits.conf | grep -v "^#" | grep -v "^$"
*       soft    core    1024
*       hard    core    2048

当前配置为:任意用户的CORE文件大小硬限制为2048,软限制为1024。(单位通常为KB)

验证:

[jiang@localhost ~]$ ulimit -Hc
2048
[jiang@localhost ~]$ ulimit -Sc
1024

我想要修改用户jiang的CORE文件大小硬限制为4096,软限制为2048。

[jiang@localhost ~]$ cat /etc/security/limits.conf | grep -v "^$" | grep -v "^#"
*       soft    core    1024
*       hard    core    2048
jiang       soft    core    2048
jiang       hard    core    4096
[jiang@localhost ~]$ ulimit -Hc
4096
[jiang@localhost ~]$ ulimit -Sc
2048

修改/etc/security/limits.conf配置文件不必重启服务,当修改完并保存后自动生效

已登录的shell(已存在的进程)是不会自动更新的,当且仅当新生成的jiang用户的shell进程会获取配置中的最新限制作为自己的资源限制值。

疑问:

我们在ulimit命令可以使用ulimited来作为一个资源的值,指代资源无限制。

但是我并未在/etc/security/limit.conf中找到类似ulimited的关键字…也就是说,我一定要给某个资源设置一个上限值?

例如,我给jiang用户设置CORE文件大小资源上限为1024KB(hard)。

我想要再次给jiang用户设置无限制无上限的值,不论是给其设置为0:

jiang hard core 0

或者注释掉这一行:

#jiang hard core 0

对于新创建的jiang的shell进程都是不起作用的,还是有一个上限值。

但是,当重启主机之后,似乎默认是jiang用户不设上限的CORE文件资源限制(hard):

[jiang@localhost ~]$ ulimit -Hc
unlimited
[jiang@localhost ~]$ ulimit -Sc
0
[jiang@localhost ~]$ ulimit -Hc unlimited
[jiang@localhost ~]$ ulimit -Hc
unlimited

有知道的小伙伴可以给我留言哈!我也多多学习下!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值