RealtimeMemTracker - 개발 재개..

2025. 6. 24. 14:09·C프로그래밍/MemoryTracker

한동안 학업과 캡스톤 프로젝트 등 여러 일이 겹치면서 개발을 잠깐 멈췄었다.
특히 이번 학기에는 전공 수업에 팀 프로젝트까지 겹쳐서, 개인 프로젝트까지 병행하긴 쉽지 않았던 것 같다.

 

이제 종강을 했으니, 다시 조금씩 개발을 재개해보려 한다.

근데 오랜만에 이전에 작성했던 소스코드를 열어보니까
전체적인 코드 구조가 머릿속에 잘 들어오질 않더라.


그래서 본격적으로 개발을 다시 시작하기 전에,
일단 지금까지 작성해놓은 코드랑 파일 구조부터 정리하고 넘어가려고 한다.

현재 프로젝트 이름은 RealtimeMemTracker이고,
구조는 아래처럼 단순하게 되어있다:

RealtimeMemTracker
|
|---header/
|    |---memory_tracker.h
|    |---process_monitor.h
|    |---ptrace_process.h
|
|---src/
     |---memory_tracker.c
     |---process_monitor.c
     |---ptrace_process.c

아직 진행을 많이 하진 않아서 파일 수도 적고,
기능도 전부 구현된 건 아니지만,
다시 시작하기 전에 현재 상태를 명확히 정리해두는 게 좋을 것 같아서 이렇게 정리해본다.

달려있는 주석은 전부 영어인데, VM에서 한글지원이 안돼서 일단 영어로 주석을 달았다.

memory_tracker.c

#include <time.h>

typedef struct syscall_event
{
	struct timespec timestamp;
	int syscall_num;
	char syscall_name[6];
	size_t cur_vmsize; //current virtual memory comsumed
	size_t cur_vmrss; //current real memory comsumed
	size_t cur_vmdata; //heap area
	size_t cur_mapped; //area that mapping by mmap
}SYSCALL_EVENT
	

void detect_memory_systemcall(int syscall_num, struct user_pt_regs *regs)
{
	if(syscall_num == 214)
	{
		printf("[Detected]: brk\n");
	}
	else if(syscall_num == 222)
	{
		printf("[Detected]: mmap\n");
	}
	else if(syscall_num == 215)
	{
		printf("[Detected]: munmap\n");
	}
}

이 파일은 시스템 콜 이벤트를 추적하기 위한 구조체 선언과,
그 중에서도 특정 시스템 콜만 필터링해서 감지하는 역할을 한다.

먼저 SYSCALL_EVENT라는 구조체가 정의되어 있고,
여기에는 다음과 같은 정보들이 담긴다:

  • 시스템 콜 발생 시각 (timestamp)
  • 시스템 콜 넘버 (syscall_num)
  • 시스템 콜 이름 (syscall_name)
  • 현재 프로세스의 메모리 사용 정보들:
    • 가상 메모리 크기 (cur_vmsize)
    • 실제 메모리 사용량 (cur_vmrss)
    • 힙 영역 크기 (cur_vmdata)
    • mmap 영역 크기 (cur_mapped)

그 아래 detect_memory_systemcall() 함수는 시스템 콜 넘버를 받아서,
특정 시스템 콜에 해당하는 경우만 감지해서 로그를 찍어준다.

현재 감지 대상으로 삼는 시스템 콜은 총 세 가지다:

  • brk: 시스템 콜 번호 214
  • munmap: 215
  • mmap: 222

따라서 이 프로그램에서는 이 세 가지 시스템 콜만 필터링해서 추적하면 된다.
(다른 시스템 콜은 무시)


process_monitor.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>

void monitor_all_process()
{
	DIR *dir = opendir("/proc");
	if(dir == NULL)
	{
		perror("opendir error");
		exit(1);
	}

	struct dirent *all_process;
	
	while((all_process = readdir(dir)) != NULL)
	{
		if(all_process->d_type == DT_DIR)
		{
			pid_t pid = atoi(all_process->d_name);
			if(pid > 0)
			{
				printf("[Monitor] PID : %d\n", pid);
			}
		}
	}
	closedir(dir);
}

int main()
{
	while(1)
	{
		system("clear");
		monitor_all_process();
		sleep(1);
	}

	return 0;
}

이 파일은 /proc 디렉토리를 열어서,

현재 실행 중인 모든 프로세스를 모니터링하는 역할을 한다.

 

monitor_all_process() 함수는 /proc 디렉토리 안에 있는 항목들을 하나씩 읽어오고,
그 중에서 디렉토리 타입(DT_DIR)이고 숫자로 된 이름(즉, 프로세스 ID)을 갖는 항목만 골라서 출력해준다.

 

즉, 현재 시스템에서 실행 중인 프로세스들의 PID를 1초 간격으로 계속 출력하는 기능이다.

main() 함수는 무한 루프 안에서 system("clear")를 이용해 화면을 지우고,
monitor_all_process()를 호출해서 실행 중인 프로세스 목록을 출력한다.


그 뒤 1초를 쉬는 방식으로 동작한다.

  • /proc 디렉토리를 열고,
  • 디렉토리 이름이 숫자인 것들만 추려서,
  • 실행 중인 프로세스들의 PID를 실시간으로 출력해주는 용도다.

 


ptrace_process.c

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/user.h>
#include <linux/elf.h> //basic binary format in Linux
#include <string.h>
#include <sys/uio.h> //for - ptrace(PTRACE_GETREGSET) call, iovec definition
#include <asm/ptrace.h> //for - struct user_pt_regs

int status; //process status

void ptrace_attach_process(pid_t pid)
{
	ptrace(PTRACE_ATTACH, pid, NULL, NULL); //chage this pid to trace mode
	waitpid(pid, &status, 0); //wait till child process stop
	printf("Attach to PID: %d\n", pid);
}

void get_syscall(pid_t pid)
{
	struct user_pt_regs regs; //structure that register status when SystemCall ocurred
	//basically SystemCall number stored to Reg[8] in arm64 Linux
	
	struct iovec io = { //from "sys/uio.h"
	        .iov_base = &regs, //register pointer
	        .iov_len = sizeof(regs) //register size
	};

	ptrace(PTRACE_GETREGSET, pid, (void *)NT_PRSTATUS, &io); //NT_PRSTATUS: select register set
	//copy process's register set to io
	
	printf("Current system call number: %llu x0: %llu, x1: %llu\n", regs.regs[8], regs.regs[0], regs.regs[1]); //based on aarch64(arm64)
}	

void ptrace_systemcall(pid_t pid)
{
        while(WIFSTOPPED(status))  //if this process stopped because of ptrace,  WIFSTOPPED(status) returns TRUE
        {
                ptrace(PTRACE_SYSCALL, pid, NULL, NULL); //stop when enter the SystemCall
                waitpid(pid, &status, 0); //
                
                if(WIFEXITED(status))
                        break;
                        
                get_syscall(pid);
                
                ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
                waitpid(pid, &status, 0);
                if(WIFEXITED(status))
                        break;
        }
}

int main()
{
	pid_t pid = fork();
	
	if(pid == 0)
	{
		int *p = (int *)malloc(sizeof(int));
		*p = 32;
		printf("child\n");
	}
	else
	{
		ptrace_attach_process(pid);
		ptrace_systemcall(pid);
		printf("parent\n");
	}

	return 0;
}

 

ptrace_attach_process(pid_t pid)

지정한 프로세스(PID)에 PTRACE_ATTACH를 걸어서 trace모드로 전환한다.

그 후, waitpid()로 자식이 stop상태로 전환될 때까지 대기한다.

 

get_syscall(pid_t pid)

PTRACE_GETREGSET을 통해 해당 프로세스의 레지스터 상태를 가져옴

ARM64에서는 시스템 콜 넘버가 reg[8]에 들어있다.

 

ptrace_systemcall(pid_t pid)

ptrace(PTRACE_SYSCALL)을 통해 해당 프로세스가 시스템 콜을 호출할 때마다 멈추게 하고,
그때마다 레지스터를 읽어서 시스템 콜 정보를 출력하는 구조.


PTRACE_ATTACH 로 외부 실행 프로세스 감시하려고 잡아두고,

PTRACE_SYSCALL로 잡아둔 프로세스의 syscall 진입을 감시한다.

 

'C프로그래밍 > MemoryTracker' 카테고리의 다른 글

RealtimeMemTracker - 4, ARM64 Linux에서 PTRACE_SYSCALL을 사용한 시스템 콜 트레이싱  (5) 2025.03.25
RealtimeMemTracker - 3, 시스템콜 번호 확인하기  (1) 2025.03.23
RealtimeMemTracker - 2, 현재 실행중인 프로세스 확인  (0) 2025.03.23
RealtimeMemTracker - 1, 다른 프로세스의 SystemCall 추적하기  (0) 2025.03.20
'C프로그래밍/MemoryTracker' 카테고리의 다른 글
  • RealtimeMemTracker - 4, ARM64 Linux에서 PTRACE_SYSCALL을 사용한 시스템 콜 트레이싱
  • RealtimeMemTracker - 3, 시스템콜 번호 확인하기
  • RealtimeMemTracker - 2, 현재 실행중인 프로세스 확인
  • RealtimeMemTracker - 1, 다른 프로세스의 SystemCall 추적하기
Minu Jin
Minu Jin
정보의 바다
  • Minu Jin
    뇌 구조가 바이너리
    Minu Jin
  • 전체
    오늘
    어제
    • 분류 전체보기
      • C프로그래밍
        • 오류해결
        • 개인 공부
        • Programming Lab(학교수업)
        • MemoryTracker
      • C++
        • 개인 공부
      • 자료구조(Data Structure)
      • ARM arch
        • Cortex-M
        • FreeRTOS
      • 컴퓨터 공학(Computer Science)
        • OS
        • 컴퓨터 구조
      • Qualcomm 기업과제
      • Linux
        • start_contribute()
        • start_analyse()
      • Web
      • 똥글
      • 백준
      • Git 학습
        • 오류해결
        • 학습중
      • Python
        • 오류해결
        • 개인 공부
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Branch
    앤드류모튼
    C++
    리눅스
    커널 기여
    포인터
    파이썬
    동적메모리
    토발즈
    자료구조
    백준
    버퍼
    Qualcomm
    커널
    Git
    시스템콜
    피보나치
    드라이버 분석
    스택
    rubikpi3
    소수
    순환
    rubik pi
    INIT
    commit
    파일 입출력
    이진 트리
    c언어
    yolo
    arm
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Minu Jin
RealtimeMemTracker - 개발 재개..
상단으로

티스토리툴바