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 추적하기
Jminu
Jminu
  • Jminu
    뇌 구조가 바이너리
    Jminu
  • 전체
    오늘
    어제
    • 분류 전체보기
      • C프로그래밍
        • 오류해결
        • 개인 공부
        • Programming Lab(학교수업)
        • MemoryTracker
      • C++
        • 개인 공부
      • 자료구조(Data Structure)
      • ARM arch
        • Cortex-M
        • FreeRTOS
      • 컴퓨터 공학(Computer Science)
        • OS
        • 컴퓨터 구조
      • Qualcomm 기업과제
      • Linux
      • Web
      • 똥글
      • 백준
      • Git 학습
        • 오류해결
        • 학습중
      • Python
        • 오류해결
        • 개인 공부
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

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

티스토리툴바