@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 |