IDT
CPU가 인터럽트나 예외 발생 시 어떤 핸들러를 실행할지 매핑해 놓은 테이블로, x86 아키텍처에서 인터럽트 처리의 핵심 자료구조입니다.
핵심 개념
| 항목 | 내용 |
| 정식 명칭 | Interrupt Descriptor Table |
| 역할 | 벡터 번호 → 핸들러(ISR) 주소 매핑 |
| 엔트리 수 | 최대 256개 (벡터 0 ~ 255) |
| 위치 관리 | IDTR 레지스터가 IDT의 시작 주소와 크기를 저장 |
| 설정 시점 | OS 부팅 시 커널이 초기화 |
IDT 구조
IDTR 레지스터
┌───────────────────┐
│ Base Address │ Limit │ ← IDT의 시작 주소와 크기
└───────┬───────────┘
│
▼
┌──────────────────────────────────┐
│ IDT (256 엔트리) │
├────────┬─────────────────────────┤
│ 벡터 0 │ Divide Error 핸들러 │
│ 벡터 1 │ Debug 핸들러 │
│ 벡터 2 │ NMI 핸들러 │
│ 벡터 3 │ Breakpoint 핸들러 │
│ ... │ ... │
│ 벡터 13 │ General Protection Fault │
│ 벡터 14 │ Page Fault 핸들러 │
│ ... │ ... │
│ 벡터 32 │ 타이머 인터럽트 핸들러 │
│ 벡터 33 │ 키보드 인터럽트 핸들러 │
│ ... │ ... │
│ 벡터 128│ 시스템 콜 핸들러 (0x80) │
│ ... │ ... │
│ 벡터 255│ ... │
└────────┴─────────────────────────┘
벡터 번호 할당 (x86)
| 범위 | 용도 | 예시 |
| 0 ~ 31 | CPU 예외 (Intel 예약) | 0: Divide Error, 13: GPF, 14: Page Fault |
| 32 ~ 47 | 하드웨어 인터럽트 (IRQ 0~15) | 32: 타이머, 33: 키보드, 46: 디스크 |
| 48 ~ 255 | OS/사용자 정의 | 128(0x80): Linux 시스템 콜 |
IDT 엔트리(디스크립터) 구조
각 엔트리는 8바이트(32비트) 또는 16바이트(64비트)로 구성됩니다.
[64비트 IDT 엔트리 - 16바이트]
┌─────────────────────────────────────────────┐
│ Offset (63:32) │ Reserved │ 상위 8바이트
├───────────┬─────┬─────┼──────────────────────┤
│ Offset(31:16) │ P │ DPL │ Type │ IST │ Selector │ 하위 8바이트
├───────────┴─────┴─────┼──────────────────────┤
│ Selector (세그먼트) │ Offset (15:0) │
└─────────────────────────────────────────────┘
| 필드 | 설명 |
| Offset | 핸들러(ISR)의 메모리 주소 (3부분으로 분할 저장) |
| Selector | 핸들러가 속한 코드 세그먼트 |
| Type | 게이트 종류 (Interrupt / Trap / Task) |
| DPL | 접근 권한 레벨 (0: 커널, 3: 사용자) |
| P | Present 비트 (1: 유효) |
| IST | Interrupt Stack Table 인덱스 |
게이트 종류
| 게이트 | 설명 | IF 플래그 |
| Interrupt Gate | 하드웨어 인터럽트 처리용 | 자동으로 클리어 (인터럽트 비활성화) |
| Trap Gate | 소프트웨어 인터럽트·예외 처리용 | 변경하지 않음 (인터럽트 허용 유지) |
| Task Gate | 태스크 전환용 (레거시, 64비트에서 미지원) | - |
IDT를 통한 인터럽트 처리 흐름
① 인터럽트/예외 발생 → 벡터 번호 결정
② CPU가 IDTR에서 IDT 시작 주소 읽기
③ IDT[벡터 번호]에서 디스크립터 조회
④ DPL 검사 (권한 확인)
⑤ Selector로 코드 세그먼트 전환
⑥ Offset 주소로 점프하여 ISR 실행
⑦ ISR 완료 후 iret으로 복귀
키보드 입력 발생 (IRQ1 → 벡터 33)
│
▼
IDTR → IDT 시작 주소 조회
│
▼
IDT[33] → 키보드 ISR 주소 + 세그먼트 + 권한 정보
│
▼
커널 모드 전환 → 키보드 ISR 실행
│
▼
iret → 원래 프로그램 복귀
IDT vs IVT (리얼 모드)
| 항목 | IVT (리얼 모드) | IDT (보호 모드) |
| 사용 모드 | 16비트 리얼 모드 | 32/64비트 보호 모드 |
| 엔트리 크기 | 4바이트 (세그먼트:오프셋) | 8바이트(32비트) / 16바이트(64비트) |
| 위치 | 고정 (물리 주소 0x0000) | 유동적 (IDTR이 가리킴) |
| 권한 검사 | 없음 | DPL로 접근 권한 제어 |
| 보안 | 취약 (누구나 수정 가능) | 커널만 수정 가능 |
시스템 콜에서의 IDT 활용 (Linux)
사용자 프로그램: read(fd, buf, size)
│
▼
eax = 0 (sys_read 번호), int 0x80 실행
│
▼
CPU → IDTR → IDT[0x80] 조회
│
▼
system_call 핸들러 진입 (entry_64.S)
│
▼
sys_call_table[eax] → sys_read() 실행
│
▼
결과 반환 → iret → 사용자 모드 복귀