시스템 호출(system calls)은 애플리케이션이나 프로세스가 운영 체제의 기능을 활용하기 위해 커널과 소통하는 기본적인 메커니즘입니다. 이번 글에서는 Linux 운영 체제에서 애플리케이션이 실행될 때 내부적으로 어떤 일이 발생하는지, 그리고 시스템 호출이 어떻게 이루어지는지를 살펴보겠습니다.
Linux 운영 체제는 두 가지 주요 메모리 영역으로 나눌 수 있습니다: 사용자 공간(user space)과 커널 공간(kernel space). 사용자 공간에는 사용자가 실행하는 애플리케이션과 프로세스가 포함되며, 이는 주로 C, Java 등의 언어로 작성됩니다. 반면, 커널 공간에는 운영 체제의 핵심 부분인 커널 코드, 커널 확장 및 디바이스 드라이버가 포함됩니다. 커널은 하드웨어와 프로세스 간의 통신을 관리하며, 시스템 자원을 효율적으로 관리합니다.
애플리케이션이 메모리나 디스크에 저장된 파일을 열고 데이터를 쓰고 싶을 때, 사용자 공간에서 실행되는 프로그램들은 커널에 특별한 요청을 합니다. 이러한 요청을 시스템 호출이라고 합니다. 예를 들어, error.log라는 빈 파일을 파일 시스템에 생성하려면 여러 시스템 호출을 수행해야 합니다. 그 중 하나는 execve 시스템 호출로, 이는 touch 바이너리를 실행하는 데 사용됩니다.
다음은 일반적인 시스템 호출의 예입니다:
open
: 파일을 여는 시스템 호출close
: 파일을 닫는 시스템 호출read
: 파일에서 데이터를 읽는 시스템 호출write
: 파일에 데이터를 쓰는 시스템 호출이제 프로세스에서 사용된 시스템 호출을 추적할 수 있는 방법을 살펴보겠습니다.
strace
유틸리티는 Linux 배포판에 기본적으로 설치되어 있으며, 애플리케이션에서 사용된 시스템 호출과 반환된 신호를 추적하는 데 유용합니다. 예를 들어, 파일 시스템에 파일을 생성할 때 사용된 시스템 호출을 검사하려면 touch 명령어 앞에 strace
명령어를 추가합니다:
$ strace touch /tmp/error.log
execve("/usr/bin/touch", ["touch", "/tmp/error.log"], 0x7ffce8f874f8 /* 23 vars */) = 0
.
.
[Output Truncated]
execve
는 프로그램을 실행하는 데 사용된 시스템 호출의 이름입니다. 첫 번째 인수는 touch 명령어의 절대 경로이며, 두 번째 인수는 touch 명령어에 전달된 인수인 문자열 배열입니다. 23 vars는 23개의 변수가 시스템 호출에 의해 상속되었음을 의미합니다.
실행 중인 프로세스에서 사용된 시스템 호출을 추적하려면 프로세스의 PID를 확인해야 합니다. 예를 들어, etcd
프로세스의 PID를 확인하려면 다음 명령어를 사용합니다.
$ pidof etcd
3596
이제 반환된 PID를 strace -p
명령어와 함께 사용하여 프로세스에 연결합니다:
$ strace -p 3596
strace: Process 3596 attached
futex(0x1ac6be8, FUTEX_WAIT_PRIVATE, 0, NULL) = 0
futex(0xc000540bc8, FUTEX_WAKE_PRIVATE, 1) = 1
이 명령어는 이제 etcd
가 수행하는 모든 시스템 호출을 출력합니다. 작업이 완료되면 Control+C
를 사용하여 명령어에서 나갈 수 있습니다.
명령어에 의해 사용된 모든 시스템 호출의 요약을 보려면 -c
플래그를 사용합니다:
$ strace -c touch /tmp/error.log
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
0.00 0.000000 0 1 read
0.00 0.000000 0 6 close
0.00 0.000000 0 2 fstat
0.00 0.000000 0 5 mmap
0.00 0.000000 0 4 mprotect
0.00 0.000000 0 1 munmap
0.00 0.000000 0 3 brk
0.00 0.000000 0 3 3 access
0.00 0.000000 0 1 dup2
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 arch_prctl
0.00 0.000000 0 3 openat
0.00 0.000000 0 1 utimensat
------ ----------- ----------- --------- --------- ----------------
100.00 0.000000 32 3 tot
이 명령어는 각 시스템 호출의 호출 횟수와 소요 시간을 요약하여 보여줍니다. 이를 통해 간단한 명령어도 여러 시스템 호출을 사용할 수 있음을 알 수 있습니다.
시스템 호출은 사용자 공간과 커널 공간 간의 중요한 인터페이스입니다. strace
와 같은 도구를 사용하면 애플리케이션이 시스템 자원에 어떻게 접근하고 사용하는지, 그리고 내부적으로 어떤 시스템 호출이 수행되는지 자세히 이해할 수 있습니다.