Linux中,getrlimit(),setrlimit(),getrusage()

一个进程在执行过程中有许多限制,比如运行时间的限制,内存使用的限制等,并且不同的用户限制不同.
在linux中,有两种方法可以获得并修改进程的限制,其一是通过系统调用,其二是在程序中调用库函数.

系统调用ulimit

通常在shell编程中用,如下:

#!/bin/bash
ulimit -m 1  #空间限制1k
ulimit -t 1  #时间限制1s
./a          #执行a

具体可参考手册,”man ulimit”.

调用库函数

通过getrlimit()获得限制,setrlimit()修改限制.
通过”man getrlimit”获得使用手册,如下:

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

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

int resource:指明何种资源,有如下资源:

1.RLIMIT_AS //进程的最大虚拟内存空间,字节为单位。
2.RLIMIT_CORE //内核转存文件的最大长度。
3.RLIMIT_CPU //最大允许的CPU使用时间,秒为单位。当进程达到软限制,内核将给其发送SIGXCPU信号,这一信号的默认行为是终止进程的执行;如果进程继续耗费CPU时间,核心会以每秒一次的频率给其发送SIGXCPU信号,直到达到硬限制,那时将给进程发送 SIGKILL信号终止其执行。
4.RLIMIT_DATA //进程数据段的最大值。
5.RLIMIT_FSIZE //进程可建立的文件的内容最大长度。如果进程试图超出这一限制时,核心会给其发送SIGXFSZ信号,默认情况下将终止进程的执行。
6.RLIMIT_LOCKS //进程可建立的锁和租赁的最大值。
7.RLIMIT_MEMLOCK //进程可锁定在内存中的最大数据量,字节为单位。
8.RLIMIT_MSGQUEUE //进程可为POSIX消息队列分配的最大字节数。
9.RLIMIT_NICE //进程可通过setpriority() 或 nice()调用设置的最大完美值。
10.RLIMIT_NOFILE //指定比进程可打开的最大文件描述词大一的值,超出此值,将会产生EMFILE错误。
11.RLIMIT_NPROC //用户可拥有的最大进程数。
12.RLIMIT_RTPRIO //进程可通过sched_setscheduler 和 sched_setparam设置的最大实时优先级。
13.RLIMIT_SIGPENDING //用户可拥有的最大挂起信号数。
14.RLIMIT_STACK //最大的进程堆栈,以字节为单位。

struct rlimit的原型声明:
struct rlimit {
rlim_t rlim_cur; /* Soft limit */
rlim_t rlim_max; /* Hard limit (ceiling for rlim_cur) */
};
rlim_t 是个int型值,类似size_t.
Soft limit即软限制,当进程所使用的资源超过Soft limit后操作系统会发送信号signal给该进程 ,Hard limit即硬限制,当进程所使用的资源达到其值时,操作系统也会发送信号给进程.当超过Solf limit时,一般程序还能运行,当超过HardSoft时,一般资源分配不成功,或者挂掉. limit小于等于Hard limit.
不同的资源操作系统发出的信号可能不同,进程收到信号处理也不相同.

以限制进程执行时间为例:

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

int main()
{

    struct rlimit r;
    if(getrlimit(RLIMIT_CPU, &r) < 0)//获得默认执行时间
    {
        perror("getrlimit error");
        exit(1);
    }
    printf("RLIMIT_CPU cur %d\n", r.rlim_cur);
    printf("RLIMIT_CPU max %d\n", r.rlim_max);
    r.rlim_cur = 1; //修改软限制
    r.rlim_max = 2; //修改硬限制
    if(setrlimit(RLIMIT_CPU, &r) < 0) //修改限制
    {
        perror("setrlimit error");
        exit(1);
    }
    if(getrlimit(RLIMIT_CPU, &r) < 0)//重新获得限制
    {
        perror("getrlimit error");
        exit(1);
    }
    printf("RLIMIT_CPU cur %d\n", r.rlim_cur);
    printf("RLIMIT_CPU max %d\n", r.rlim_max);
    while(1) //测试超时系统的反应
        ;
    return 0;
}

编译执行:
gcc test.c -o test
./test
结果:
RLIMIT_CPU cur -1
RLIMIT_CPU max -1
RLIMIT_CPU cur 1
RLIMIT_CPU max 2
CPU time limit exceeded (core dumped)

getrusage()

程序执行过程中,可一通过库函数的调用,可查看进程执行过程中的信息,库函数getrusage().
同理查看手册,”man getrusage”:

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

 int getrusage(int who, struct rusage *usage);

int who:指明查看谁的信息.
可以查看该进程的信息,也可查看由该进程创建子进程的信息,who = 0则表示自己,who = -1则表示子进程.

struct rusage *usage的原型声明:

struct rusage {
struct timeval ru_utime; /* user time used */
struct timeval ru_stime; /* system time used */
long ru_maxrss; /* max resident set size */
long ru_ixrss; /* integral shared memory size */
long ru_idrss; /* integral unshared data */
long ru_isrss; /* integral unshared stack */
long ru_minflt; /* page reclaims */
long ru_majflt; /* page faults */
long ru_nswap; /* swaps */
long ru_inblock; /* block input operations */
long ru_oublock; /* block output operations */
long ru_msgsnd; /* messages sent */
long ru_msgrcv; /* messages received */
long ru_nsignals; /* signals received */
long ru_nvcsw; /* voluntary context switches */
long ru_nivcsw; /* involuntary ” */
};

下面以查看本进程的信息为例:

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

int main()
{
    struct rusage start, end;
    if(getrusage(0, &start) < 0) //获得开始的信息 
    {
        perror("getrusage error");
        exit(1);
    }
    int k = 0;
    for(int i = 0; i < (int)1e10; ++i);
        k++;
    if(getrusage(0, &end) < 0) //获得结束的信息 
    {
        perror("getrusage error");
        exit(1);
    }
    //用户态执行时间
    double usertime = (end.ru_utime.tv_sec - start.ru_utime.tv_sec) + (end.ru_utime.tv_usec - start.ru_utime.tv_usec) / 10e6; 
    //内核态执行时间
    double kerneltime = (end.ru_stime.tv_sec - start.ru_stime.tv_sec) + (end.ru_stime.tv_usec - start.ru_stime.tv_usec) / 10e6;     printf("usertime %lf, kerneltime %lf\n", usertime, kerneltime); 
    printf("max resident set size %ld\n", start.ru_maxrss);
    printf("integral shared memory size %ld\n", start.ru_ixrss);
    return 0;
}

编译运行:
gcc test.c -o test
./test
结果:
usertime 4.041600, kerneltime 0.000400
max resident set size 1876
integral shared memory size 0

更加详细的文章: getrlimit,setrlimit,getrusage
更多细节,请自主查看man手册.

你可能感兴趣的:(linux,setrlimit,getrlimit,getrusage)