linux c进程资源

每个进程都会消耗诸如内存和CPU时间之类的系统资源,本文将介绍与资源相关的系统调用。

#include <sys/resource.h>

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

//Returns 0 on success, or –1 on error

getrusage() 系统调用返回调用进程或子进程用掉的各类系统资源统计信息,利用此函数,父进程可以监控子进程cpu和内存的使用量。

who参数可以指定为以下:

RUSAGE_SELF 返回调用进程相关信息。
RUSAGE_CHILDREN 返回调用进程的所有被终止和处于等待状态的子进程相关信息。
RUSAGE_THREAD 返回调用线程相关信息。

rusage结构定义如下,不懂英文的可以参考这篇文章对一些资源的文字解释 linux命令date、time

struct rusage {
    struct timeval ru_utime; /* User CPU time used */
    struct timeval ru_stime; /* System CPU time used */
    long ru_maxrss; /* Maximum size of resident set (kilobytes)
                    [used since Linux 2.6.32] */
    long ru_ixrss; /* Integral (shared) text memory size
                    (kilobyte-seconds) [unused] */
    long ru_idrss; /* Integral (unshared) data memory used
                    (kilobyte-seconds) [unused] */
    long ru_isrss; /* Integral (unshared) stack memory used
                    (kilobyte-seconds) [unused] */
    long ru_minflt; /* Soft page faults (I/O not required) */
    long ru_majflt; /* Hard page faults (I/O required) */
    long ru_nswap; /* Swaps out of physical memory [unused] */
    long ru_inblock; /* Block input operations via file
                    system [used since Linux 2.6.22] */
    long ru_oublock; /* Block output operations via file
                    system [used since Linux 2.6.22] */
    long ru_msgsnd; /* IPC messages sent [unused] */
    long ru_msgrcv; /* IPC messages received [unused] */
    long ru_nsignals; /* Signals received [unused] */
    long ru_nvcsw; /* Voluntary context switches (process
                    relinquished CPU before its time slice
                        expired) [used since Linux 2.6] */
    long ru_nivcsw; /* Involuntary context switches (higher
                    priority process became runnable or time
                    slice ran out) [used since Linux 2.6] */
};

进程资源限制

每个进程都用一组资源限制值,它们可以用来限制进程能够消耗的各种系统资源。shell的内置命令ulimit可以设置shell的资源限制。用shell创建的进程会继承这些限制。

linux下的/proc/PID/limits文件可以查看任意进程的所有资源限制。

#比如我的其中一个进程显示如下
[root@izj6cfw9yi1iqoik31tqbgz c]# cat /proc/1841/limits 
Limit                     Soft Limit           Hard Limit           Units     
Max cpu time              unlimited            unlimited            seconds   
Max file size             unlimited            unlimited            bytes     
Max data size             unlimited            unlimited            bytes     
Max stack size            8388608              unlimited            bytes     
Max core file size        0                    unlimited            bytes     
Max resident set          unlimited            unlimited            bytes     
Max processes             3895                 3895                 processes 
Max open files            65535                65535                files     
Max locked memory         65536                65536                bytes     
Max address space         unlimited            unlimited            bytes     
Max file locks            unlimited            unlimited            locks     
Max pending signals       3895                 3895                 signals   
Max msgqueue size         819200               819200               bytes     
Max nice priority         0                    0                    
Max realtime priority     0                    0                    
Max realtime timeout      unlimited            unlimited            us

下面2个系统调用用来读取和修改自己的资源限制

#include <sys/resource.h>

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

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

//Both return 0 on success, or –1 on error

软限制 规定了进程能够消耗的数量。一个进程可以将软限制调整为从0到硬限制之间的值。对于大多数资源来讲,硬限制 的唯一作用是为软限制设定上限。特权进程能够增大或缩小硬限制(必须大于软限制),非特权进程则能缩小硬限制(不可逆)。rlim_cur和 rlim_max 取值为RLIM_INFINITY 表示没有限制。

resource的取值如下:

资源  限制
RLIMIT_AS 进程虚拟内存限制大小-字节
RLIMIT_CORE 核心文件大小-字节
RLIMIT_CPUCPU时间-s
RLIMIT_DATA 进程数据段-字节
RLIMIT_FSIZE 文件大小-字节
RLIMIT_MEMLOCK 锁住的内存-字节
RLIMIT_MSGQUEUE 为真实用户id分配posix消息队列-字节
RLIMIT_NICE nice值
RLIMIT_NOFILE 最大文件描述符+1
RLIMIT_NPROC 真实用户id下的进程数量
RLIMIT_RSS 
RLIMIT_RTPRIO 实时调度策略
RLIMIT_RTTIME 实时cpu时间 - 微妙
RLIMIT_SIGPENDING 真实用户id信号队列中的信号数
RLIMIT_STACK 栈段的大小

例子

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <pthread.h>

#include <sys/resource.h>

int printRlimit(const char *msg, int resource);

int printRlimit(const char *msg, int resource){
    struct rlimit rlim;

    if (getrlimit(resource, &rlim) == -1)
        return -1;

    printf("%s soft=", msg);
    if (rlim.rlim_cur == RLIM_INFINITY)
        printf("infinite");
#ifdef RLIM_SAVED_CUR           /* Not defined on some implementations */
    else if (rlim.rlim_cur == RLIM_SAVED_CUR)
        printf("unrepresentable");
#endif
    else
        printf("%lld", (long long) rlim.rlim_cur);

    printf("; hard=");
    if (rlim.rlim_max == RLIM_INFINITY)
        printf("infinite\n");
#ifdef RLIM_SAVED_MAX           /* Not defined on some implementations */
    else if (rlim.rlim_max == RLIM_SAVED_MAX)
        printf("unrepresentable");
#endif
    else
        printf("%lld\n", (long long) rlim.rlim_max);

    return 0;
}

int main(int argc, char *argv[]){
    struct rlimit rl;
    int j;
    pid_t childPid;

    if (argc < 2 || argc > 3 || strcmp(argv[1], "--help") == 0){
        printf("%s soft-limit [hard-limit]\n", argv[0]);
        return 1;
    }

    printRlimit("Initial maximum process limits: ", RLIMIT_NPROC);

    rl.rlim_cur = (argv[1][0] == 'i') ? RLIM_INFINITY : atoi(argv[1]);
    rl.rlim_max = (argc == 2) ? rl.rlim_cur :
                (argv[2][0] == 'i') ? RLIM_INFINITY : atoi(argv[2]);
    if (setrlimit(RLIMIT_NPROC, &rl) == -1)
        perror("setrlimit");

    printRlimit("New maximum process limits:     ", RLIMIT_NPROC);
    
    //在这里尽可能多的创建进程
    //return 0;
    for (j = 1; ; j++) {
        switch (childPid = fork()) {
        case -1: perror("fork");

        case 0: _exit(EXIT_SUCCESS);            /* Child */

        default:        /* Parent: display message about each new child
                           and let the resulting zombies accumulate */
            printf("Child %d (PID=%ld) started\n", j, (long) childPid);
            break;
        }
    }
}
#先切换成普通用户
[root@izj6cfw9yi1iqoik31tqbgz c]# su nobody
bash-4.2$ ./a.out 10 20
Initial maximum process limits:  soft=3895; hard=3895
New maximum process limits:      soft=10; hard=20
Child 1 (PID=21364) started
Child 2 (PID=21365) started
Child 3 (PID=21366) started
Child 4 (PID=21367) started
fork: Resource temporarily unavailable

上面显示只创建了4个子进程,这是因为nobody已经有6个进程


上一篇: linux c使用syslog记录消息
下一篇: linux c共享库(动态库)基础(1)
作者邮箱: 203328517@qq.com