컴퓨터공학

시스템 호출(System Call)과 주요 종류

nyambu 2025. 3. 27. 13:01

시스템 호출(System Call)과 주요 종류
시스템 호출(System Call)과 주요 종류

1. 시스템 호출(System Call)이란?

 운영체제(OS)는 사용자와 하드웨어 사이를 중개하는 역할을 한다. 그런데 사용자가 프로그램을 실행하거나 파일을 열고, 데이터를 전송하고, 프로세스를 종료하는 등의 작업을 수행할 때마다, 운영체제는 어떻게 이를 인식하고 처리할까? 바로 이때 시스템 호출(System Call)이라는 개념이 등장한다. 시스템 호출(System Call)은 사용자 프로그램(User Mode)에서 운영체제 커널(Kernel Mode)의 기능을 요청할 수 있도록 해주는 인터페이스다. 쉽게 말해, 사용자 프로그램이 OS에게 “이거 해줘!”라고 부탁하는 공식적인 창구라고 볼 수 있다.

1-1. 왜 시스템 호출이 필요한가?

 일반 프로그램은 하드웨어를 직접 제어할 수 없다. 예를 들어, 파일을 읽거나, 메모리를 할당하거나, 네트워크로 데이터를 전송하는 등의 작업은 모두 하드웨어와 밀접하게 연결되어 있기 때문에 보안과 안정성을 위해 운영체제가 그 권한을 가지고 있다. 그래서 사용자는 직접 하드웨어에 접근하는 대신, 운영체제에게 "이 작업을 대신해줘"라고 요청하게 되며, 이때 사용하는 것이 바로 시스템 호출이다.

 

1-2. 시스템 호출의 구조

 시스템 호출은 다음과 같은 흐름으로 동작한다.

  1. 사용자 프로그램이 시스템 호출 API를 호출 (예: open(), read(), fork() 등)
  2. 해당 API는 내부적으로 커널에 인터럽트를 발생시킴
  3. 커널 모드로 전환된 후 시스템 호출 핸들러가 실행됨
  4. 운영체제가 해당 요청을 수행하고 결과를 반환
  5. 다시 사용자 모드로 돌아와 결과를 사용자 프로그램에 전달

📌 이처럼 시스템 호출은 API → 커널 인터럽트 → 처리 → 반환 흐름으로 진행된다.


2. 시스템 호출의 종류

 시스템 호출은 그 역할에 따라 여러 종류로 나뉘며, 운영체제가 제공하는 기능 대부분이 시스템 호출을 통해 구현된다. 주요 분류는 다음과 같다.

2-1. 프로세스 제어(Process Control)

프로세스 생성, 종료, 실행 등과 관련된 기능을 수행한다.

  • fork() : 새로운 프로세스를 생성
  • exec() : 새로운 프로그램으로 현재 프로세스를 대체
  • exit() : 프로세스를 종료
  • wait() : 자식 프로세스가 종료될 때까지 대기

📌 예시: 리눅스에서 fork()를 사용하면 하나의 부모 프로세스가 자식 프로세스를 생성할 수 있다. 이는 서버에서 여러 클라이언트를 처리할 때 많이 사용된다.

 

2-2. 파일 조작(File Manipulation)

 파일을 열고, 읽고, 쓰고, 닫는 기능을 담당한다.

  • open() : 파일 열기
  • read() : 파일에서 데이터 읽기
  • write() : 파일에 데이터 쓰기
  • close() : 파일 닫기

📌 예시: 사용자가 텍스트 파일을 열어서 내용을 수정하고 저장할 때, 내부적으로는 이 네 가지 시스템 호출이 연속적으로 발생하게 된다.

 

2-3. 디바이스 제어(Device Manipulation)

 입출력 장치(I/O Device)를 제어하는 기능이다.

  • ioctl() : 장치에 대한 제어 명령 전송
  • read() / write() : 장치로부터 데이터 읽기/쓰기
  • mmap() : 메모리 매핑된 I/O 처리

📌 예시: 마우스나 키보드를 사용할 때도 이 시스템 호출이 백그라운드에서 동작하고 있다.

 

2-4. 정보 유지(Information Maintenance)

 시스템 정보, 파일 정보, 프로세스 정보 등을 얻거나 설정할 때 사용한다.

  • getpid() : 현재 프로세스 ID 가져오기
  • gettimeofday() : 현재 시간 정보
  • uname() : OS 버전 정보
  • alarm() : 특정 시간 이후에 알림

📌 예시: 로그 기록을 위해 현재 시간을 확인하거나, 특정 조건에 따라 경고음을 울릴 때 사용된다.

 

2-5. 메모리 관리(Memory Management)

 프로세스가 실행될 메모리를 할당하거나 해제하는 작업이다.

  • brk(), sbrk() : 힙 메모리 영역 확장
  • mmap() : 메모리를 특정 주소에 매핑
  • munmap() : 매핑된 메모리 해제

📌 예시: 동적 메모리 할당 (malloc)도 내부적으로는 시스템 호출을 통해 힙 메모리를 요청한다.

 

2-6. 통신(Communication)

 프로세스 간 통신(IPC), 네트워크 통신 등에 사용된다.

  • pipe() : 익명 파이프 생성
  • shmget() / shmat() : 공유 메모리 할당/접근
  • socket() : 네트워크 소켓 생성
  • bind(), connect(), listen(), accept() : TCP 연결 관리

📌 예시: 채팅 프로그램에서 메시지를 주고받는 과정은 대부분 socket() 기반 시스템 호출로 이루어진다.


3. 시스템 호출의 내부 동작 원리

운영체제는 사용자 모드(User Mode)와 커널 모드(Kernel Mode)라는 두 가지 실행 모드를 가진다. 시스템 호출이 중요한 이유는 이 두 모드를 안전하게 전환하는 핵심 도구이기 때문이다.

3-1. 사용자 모드와 커널 모드

  • 사용자 모드: 일반 프로그램이 실행되는 영역, 하드웨어 접근 제한
  • 커널 모드: 운영체제가 실행되는 영역, 하드웨어 접근 가능

 사용자가 시스템 호출을 통해 커널에게 요청하면, 모드 전환이 발생하고, 커널 모드에서 요청을 처리한 뒤 다시 사용자 모드로 돌아간다. 이렇게 모드 전환이 가능하도록 설계되어 있기 때문에, 운영체제는 시스템을 보호하면서도 효율적인 자원 사용을 보장할 수 있다.


4. 시스템 호출의 예시와 실무 적용

4-1. 시스템 프로그래밍에서의 활용

C 언어에서 직접 시스템 호출을 다룰 수 있으며, 이는 고성능 서버나 OS 개발에서 매우 중요한 요소다.

#include <unistd.h>
#include <stdio.h>

int main() {
    pid_t pid = fork(); // 자식 프로세스 생성
    if (pid == 0) {
        printf("Child process\n");
    } else {
        printf("Parent process, PID: %d\n", pid);
    }
    return 0;
}

 

이 코드에서 fork()는 시스템 호출이며, 새로운 프로세스를 생성한다.

4-2. 웹 서버, DBMS, 쉘 환경 등

  • Apache, Nginx 같은 웹 서버는 fork()나 epoll() 같은 시스템 호출로 클라이언트 요청을 처리
  • MySQL, PostgreSQL 같은 DBMS도 내부적으로 많은 시스템 호출을 사용하여 데이터 입출력
  • Linux 쉘(bash)에서 ps, top, kill 등의 명령어를 입력하면 내부적으로 시스템 호출이 작동

5. 시스템 호출 vs 라이브러리 함수

 시스템 호출과 라이브러리 함수는 혼동되기 쉽다.

항목 시스템 호출 라이브러리 함수
정의 OS 커널 기능 요청 기능 모듈화된 함수
속도 느릴 수 있음 (모드 전환 필요) 빠름 (모드 전환 없음)
예시 write(), fork() printf(), strlen()
접근 커널 모드 접근 가능 사용자 모드에서만 동작

📌 printf()는 내부적으로 write() 시스템 호출을 사용하여 출력을 수행한다. 즉, 라이브러리 함수는 시스템 호출을 감싸는 래퍼(wrapper)로 동작하는 경우가 많다.


6. 시스템 호출의 보안 고려 사항

시스템 호출은 커널 기능에 직접 접근하는 창구이므로, 보안상의 허점이 생기면 치명적인 결과를 초래할 수 있다.

  • 사용자 입력 검증 없이 시스템 호출을 사용할 경우, 권한 상승(Escalation) 공격 발생 가능
  • 커널 모드에서 취약점이 발생하면 전체 시스템이 무력화될 수 있음
  • 따라서 모든 시스템 호출에는 검증, 권한 체크, 예외 처리가 철저히 수행되어야 한다.

📌 최근의 보안 기술들인 시스템 콜 필터링(Linux seccomp), 샌드박싱(sandboxing) 등이 시스템 호출의 사용을 제한하거나 감시하는 목적으로 도입되었다.