리눅스에서 C 프로그래밍을 하다 보면 가끔 시스템정보를 알아야 할 때가 있습니다.
메모리, 사용메모리, 프로세서 사용률 등의 정보입니다. 그때 편하게 개발 가능한 방법은 TOP 명령어를 파싱하는 방법입니다.
우선 TOP 명령어에 대해서 간단히 설명 드리겠습니다.
TOP 명령
top 명령은 활성 Linux 프로세스를 표시하는 데 사용되고 실행 중인 시스템의 동적 실시간 보기를 제공합니다.
또한 시스템의 요약 정보와 현재 Linux 커널에서 관리하는 프로세스 또는 스레드 목록을 표시합니다.
리눅스 명령창에 “top” 을 타이핑 해 보겠습니다.
출력형식의 상위 부분은 프로세스 및 리소스 사용량 통계가 포함된 대화형 명령 모드 창이 열립니다.
아래쪽은 현재 실행 중인 프로세스 목록이 포함되어 있습니다.
상당 표시항목
라인 1 | 현재시간과 부팅후 흐른시간, users(), load average(각각 1, 5, 15 분 동안의 평균 시스템 부하량 평균값) |
Tasks | 총 쓰레드 표시 running, sleeping, stopped, zombie 로 분류됨. |
%Cpu(s) | 새로 고침 이후 간격을 기준으로 한 CPU 상태율을 표시함. |
us, user – un-niced 사용자 프로세스를 실행하는 시간 sy, system – 커널 프로세스 실행 시간 ni, nice – niced 사용자 프로세스 실행 시간 id, idle – 커널 idle 핸들러에서 보낸 시간 wa, IO-wait – I/O 완료를 기다리는 시간 hi – 하드웨어 인터럽트 서비스에 소요 된 시간 si – 소프트웨어 인터럽트 서비스에 소요 된 시간 st – Hypervisor VM 에 할당된 시간 |
|
KiB Mem | 물리적 메모리를 반영함 분류는 total, free, used, buff/cache 로 구분됨. |
Kib Swap | 가상 메모리를 반영함 분류는 total, free, used, avail Mem |
하단 표시 항목
PID | 작업의 고유한 프로세스 ID를 표시합니다. |
USER | 작업 소유자의 사용자 이름입니다. |
PR | 작업의 우선 순위를 나타냅니다. |
NI | 작업의 좋은 가치를 나타냅니다. 음의 좋은 값은 높은 우선 순위를 의미하고, 좋은 값이 양이면 우선 순위가 낮다는 것을 의미합니다. |
VIRT | 태스크에서 사용하는 총 가상 메모리입니다. |
RES | 프로세스에서 사용하는 실제 실제 메모리의 양을 나타냅니다. |
SHR | 작업에서 사용하는 공유 메모리 크기(kb)를 나타냅니다. |
S | 프로세스의 상태입니다. |
%CPU | CPU 사용량을 나타냅니다. |
%MEM | 작업의 메모리 사용량을 표시합니다. |
TIME+ | CPU 시간, ‘TIME’과 동일하지만 100분의 1초를 통해 더 많은 세분성을 반영합니다. |
COMMAND | 실행 중인 명령입니다. |
top 실행 옵션
- -b : 배치모드 옵션
- -n : top 실행 주기를 설정
- -p : process ID
top 명령으로 출력문 가져오기
top 을 실행하면 입력문처럼 항상 떠 있는 것을 볼 수 있습니다.
‘q’ 또는 Ctrl+C 를 타이핑 해야만 탈출 할 수 있습니다.
출력문을 파싱하기 위해서는 한번 실행후 그 값을 문자열로 받아와야겠지요.
한번 실행 하고 자동종료 되게끔 해보겠습니다.
top -n1
을 타이핑하면 화면에서 한번 출력되고 종료가 됩니다.
출력문을 문자열로 받아오는 방법은 이전에 소개 드렸습니다.
[C] Linux 의 쉘명령 출력을 변수로 받기 (harostudio.co.kr)
출력 파싱하기
이렇게 정형화된 문자열을 파싱하는 좋은 방법으로는 sscanf 라는 함수가 존재합니다.
정형화된 문자열을 파싱하기에 더할 나위 없이 좋은 함수 입니다.
man page 에서 sscanf 에 대해 잠시 살펴 보겠습니다.
sscanf()
sscanf() 함수는 buffer에서 argument-list가 제공하는 위치로 데이터를 읽습니다.
각 argument는 format-string에 서 유형 지정자에 대응하는 유형의 변수에 대한 포인터여야 합니다.
리턴값
sscanf() 함수는 성공적으로 변환 및 지정된 필드 수를 리턴합니다. 리턴값은 읽었지만 지정되지 않은 필드는 포함하지 않습니다.
리턴값은 변환 전에 스트링 끝이 나타난 경우 EOF입니다.
format
%[*][폭(width)][한정자(modifiers)]타입(type)
종류 | 설명 |
---|---|
* | 데이터를 stdin 에서 받아들이지만 무시된다. 물론, 이에 대응되는 인자에는 받아들인 데이터가 저장되지 않고 이 인자는 다음 형식 태그에 대응된다. 예를 들어 scanf("%*d%d", i,j); 의 경우 먼저 수를 입력하더라도 %*d 형식이므로 무시 된다. 그 다음 수를 입력하면 %d 형식 태그가 j 가 아닌 i 에 대응되어 i 에 그 다음 입력한 수가 들어가게 된다. 이 때 j 에는 아무런 값도 들어가지 않는다. |
폭 | stdin 에서 읽어들일 최대 문자 수를 지정한다. 예를 들어 scanf("%10s", str); 로 했을 경우 stdin 에서 최대 10 문자를 읽어와 str 에 저장한다. 이 때 주의할 점은 str 에는 NULL 문자가 들어갈 수 있는 충분한 공간이 남아 있어야 한다. |
한정자 | 입력받는 데이터의 크기를 지정한다. int, unsigned int, float 형에 대해 입력받는 데이터의 크기를 설정할 수 있다. h 의 경우 short int (d, i, n 의 경우) 혹은 unsigned short int (o, u, x 일 경우). l 의 경우 long int (d, i, n 의 경우) 혹은 unsigned long int (o, u, x 일 경우), 혹은 double (e, f, g 일 경우). 마지막으로 L 의 경우 long double (e, f, g 일 경우) 에 사용할 수 있다. |
타입 | 데이터를 어떠한 형식으로 혹은 어떠한 값만을 읽어들어야 할 지에 대해 지정해준다. 아래 표를 참고. |
타입 | 대응되는 입력 방식 | 대응되는 인자의 형태 |
---|---|---|
d | 십진법으로 표현된 정수: 말그대로 십진법으로 쓰인 정수로, + 나 - 기호로 시작할 수도 있다. | int * |
e, E, f, g, G | 부동 소수점: 소수점을 포함하고 있는 소수(decimal number) 로 + 나 - 기호로 시작할 수도 있으며, e 나 E 문자(10 의 지수를 나타내기 위해)를 포함할 수 도 있다. -732.103, 12e-4, +123.10 은 모두 올바른 입력이다. | float * |
o | 8진법으로 표현된 정수 | int * |
s | 문자열: 공백문자를 찾을 때 까지 문자들을 읽어들인다. | char * |
u | 부호가 없는 십진법으로 표현된 정수 | unsigned int * |
x, X | 16진법으로 표현된 정수 | int * |
예제 코드
예제로 시스템의 물리적 메모리의 전체, 여유공간, 사용 공간을 출력하는 프로그램을 보여드리겠습니다.
#include <stdio.h>
int run_shell_command(char *command, char *output, int *out_len)
{
int result;
if (!command) return -1;
result = -1;
if (output)
{
FILE* file;
file = popen(command, "r");
if (file)
{
*out_len = fread(output, 1, *out_len - 1, file);
if (*out_len >= 0)
output[*out_len] = 0;
else
output[0] = 0;
result = pclose(file);
}
}
else
{
result = System(command);
}
return result;
}
int main()
{
char output[512];
int length = 512;
int total, free, used;
run_shell_command("top -n1 | grep \"KiB Mem\"", output, &length);
int chk = sscanf(output, "KiB Mem %*s %d %*s %d %*s %d", &total, &free, &used);
printf("total memory : %d \nfree memory : %d\nused memory %d\n", total, free, used);
}
위와 같이 코딩하고 출력내용을 샆펴 보겠습니다.
아주 간단하고 쉽게 top 명령어중 필요한 값을 파싱해서 출력하는 프로그램을 만들어 보았습니다.