트랩
프로그램이 의도적으로 발생시키는 소프트웨어 인터럽트로, 사용자 모드에서 커널 모드로 전환하기 위한 동기적(synchronous) 메커니즘입니다.
트랩 vs 인터럽트 vs 예외
| 항목 | 트랩(Trap) | 인터럽트(Interrupt) | 예외(Exception) |
| 발생 원인 | 프로그램이 의도적으로 발생 | 하드웨어 장치가 발생 | 프로그램 오류로 발생 |
| 동기/비동기 | 동기적 | 비동기적 | 동기적 |
| 예시 | 시스템 콜, 디버그 브레이크포인트 | 키보드 입력, 타이머, 디스크 I/O 완료 | 0으로 나누기, 페이지 폴트 |
| 의도성 | 의도적 | 외부에서 발생 | 비의도적 |
| 복귀 지점 | 다음 명령어 | 중단된 명령어의 다음 | 현재 또는 다음 명령어 |
트랩의 동작 흐름
┌─────────────── 사용자 모드 ───────────────┐
│ │
│ ① 프로그램이 시스템 콜 호출 (예: read()) │
│ ② 라이브러리가 시스템 콜 번호를 레지스터 저장 │
│ ③ trap 명령어 실행 (x86: int 0x80 / syscall) │
│ │ │
├───────────── 모드 전환 ──────────────────┤
│ ▼ │
│ ④ CPU가 현재 상태(레지스터, PC) 저장 │
│ ⑤ IDT에서 트랩 핸들러 주소 조회 │
│ ⑥ 커널 핸들러 실행 (요청 처리) │
│ ⑦ 결과 저장 후 iret 명령으로 복귀 │
│ │ │
├───────────── 모드 복귀 ──────────────────┤
│ ▼ │
│ ⑧ 사용자 프로세스가 결과를 받고 계속 실행 │
└──────────────────────────────────────────┘
트랩이 사용되는 대표적인 경우
| 용도 | 설명 | 예시 |
| 시스템 콜 | 커널 기능 요청 | read(), write(), fork() |
| 디버깅 | 브레이크포인트 설정 | x86의 int 3 명령어 |
| 가상 머신 | 게스트 OS의 특권 명령을 호스트가 에뮬레이션 | VMM의 trap-and-emulate |
x86 아키텍처에서의 트랩 명령어
| 명령어 | 용도 | 특징 |
int 0x80 | 레거시 리눅스 시스템 콜 | 느림 (IDT 조회 필요) |
syscall | 최신 리눅스 시스템 콜 (x86-64) | 빠름 (MSR 레지스터 기반) |
sysenter | Windows/Intel 시스템 콜 | syscall과 유사 |
int 3 | 디버그 브레이크포인트 | 1바이트 명령어 (0xCC) |
Java에서의 트랩 발생 예시
// 아래 코드 실행 시 JVM 내부에서 트랩이 발생하여 커널 모드로 전환됨
// 1. 파일 I/O → open() 시스템 콜 → 트랩 발생
FileInputStream fis = new FileInputStream("data.txt");
// 2. 콘솔 출력 → write() 시스템 콜 → 트랩 발생
System.out.println("hello");
// 3. 스레드 생성 → clone() 시스템 콜 → 트랩 발생
new Thread(() -> System.out.println("thread")).start();
// 4. 일반 연산 → 트랩 발생하지 않음 (사용자 모드에서 처리)
int sum = 1 + 2;
String s = "hello".toUpperCase();
트랩과 인터럽트의 처리 구조
둘 다 IDT(Interrupt Descriptor Table)를 통해 핸들러를 찾지만, 발생 원인이 다릅니다.
┌──── 트랩 (소프트웨어, 동기) ────┐
│ │
▼ │
┌──────────────┐ │
│ IDT │ ← 벡터 번호로 핸들러 조회 │
│ (256개 엔트리) │ │
└──────┬───────┘ │
▼ │
커널 핸들러 실행 │
│ │
▼ │
└──── 인터럽트 (하드웨어, 비동기) ──┘