본문 바로가기

C/C++

C 프로세스 자원 사용량 확인하기

 @markdown


# C 프로세스 자원 사용량 확인하기


프로세스의 자원 사용 정보를 런타임에 확인 할 수 있는 C 소스코드.

이 코드는 **리눅스에서만 동작**한다. 열심히 찾아봤지만,  C를 사용해 플랫폼 독립적으로 이 기능을 구현할 방법은 없었다.

_

리눅스에는 `/proc/{pid}/status`파일을 읽어 현재 프로세스의 자원 사용량 정보를 알 수 있다.

이 점을 활용해, 해당 파일을 파싱해 자원 사용량을 알아내도록 했다. 아쉬운 점이라면 C 라이브러리에서 공식적으로 제공하는 방법이 아니므로 리눅스 버전에 따라서 결과가 달라질 수 있다는 것.



## 소스 코드


`rusage_create()`  의 매개변수로 0을 넣으면 자기 자신을, 0이 아닌 값을 넣으면 해당 pid를 갖는 프로세스의 자원 사용량을 확인할 수 있다.

실제 사용 예제는 아래에서 확인하자.

_


### rusage.h


```

#ifndef RUSAGE_RUSAGE_H

#define RUSAGE_RUSAGE_H


#include <stdlib.h>


typedef struct {

    char* key;

    char* value;

} Entity;


typedef struct {

    Entity* entities;

    size_t size;

    size_t capacity;

} EntitySet;



EntitySet rusage_create(pid_t pid);


void rusage_destroy(EntitySet es);


char* rusage_getstr(EntitySet* es, char* key, char* def);


#endif //RUSAGE_RUSAGE_H

```


### rusage.c


```

#include <stdio.h>

#include <string.h>


#include "rusage.h"


#define ALPAH "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

#define NUMERIC "0123456789"


static char* strstran(char* s) {

    return strpbrk(s, ALPAH NUMERIC);

}


EntitySet rusage_create(pid_t pid) {

    EntitySet usage;

    usage.entities = calloc(60, sizeof(Entity));

    usage.capacity = 60;

    usage.size = 0;


    char path[100] = {0,};

    if(pid == 0) strcat(path, "/proc/self/status");

    else snprintf(path, sizeof(path) - 1, "/proc/%d/status", abs(pid));


    FILE* status = fopen(path, "r");

    if(!status) {

        perror("cannot open status file");

        return usage;

    }


    char buf[65535];

    while(fgets(buf, sizeof(buf) - 1, status) && usage.size < usage.capacity) {

        buf[strlen(buf) - 1] = '\0';

        char* key = buf;

        char* value = strchr(buf, ':') + 1;

        *(value - 1) = '\0';

        value = strstran(value);

        if(value) {

            char* space = strpbrk(value, " \t");

            if(space)

                *space = '\0';

        }


        Entity* e = &usage.entities[usage.size++];

        e->key = strdup(key);

        e->value = strdup(value ? value : "");

    }


    fclose(status);

    return usage;

}


void rusage_destroy(EntitySet es) {

    for(int i = 0; i < es.size; ++i) {

        Entity* e = &es.entities[i];

        free(e->key);

        free(e->value);

        memset(e, 0, sizeof(Entity));

    }

    free(es.entities);

    memset(&es, 0, sizeof(es));

}


char* rusage_getstr(EntitySet* es, char* key, char* def) {

    for(int i = 0; i < es->size; ++i) {

        Entity* e = &es->entities[i];

        if(strcmp(key, e->key) == 0)

            return e->value[0] ? es->entities[i].value : def;

    }

    return def;

}


```



## 사용 예제


현재 프로세스의 모든 사용량 정보를 출력하고, 메모리 사용량을 출력하는 예제.


```

#include <stdio.h>

#include "rusage.h"


int main() {

    EntitySet usage = rusage_create(0);

    for(int i = 0; i < usage.size; ++i) {

        Entity e = usage.entities[i];

        printf("Entity[%d]\n", i);

        printf("    key: '%s'\n", e.key);

        printf("    key: '%s'\n", e.value);

    }


    char* key = "VmSize";

    printf("Value of '%s' is: '%s'\n", key, rusage_getstr(&usage, key, "nil"));


    rusage_destroy(usage);

    return EXIT_SUCCESS;

}

```

'C/C++' 카테고리의 다른 글

Nonblocking I/O in C  (0) 2017.04.03
pthread detach  (0) 2017.02.11
C 동적 라이브러리를 사용하는 프로그램 만들기  (0) 2017.01.25
C String Utility  (0) 2016.12.22
C printStackTrace  (0) 2016.12.02