인터럽트 (Interrupt)
프로그램을 실행하는 도중 예기치 못한 상황이 발생할 경우
CPU가 현재 수행 중인 작업을 일시 중단하고, 다른 작업을 수행하도록 하는 메커니즘
구조
하드웨어 장치마다 `컨트롤러`라고 불리는 작은 CPU 존재
컨트롤러는 장치로부터 출입하는 데이터를 임시로 저장하기 위한 `Local Buffer`라는 `작은 메모리`를 가짐
ex) 디스크 = 디스크 컨트롤러 / 메모리= 메모리 컨트롤러
개념
가정 : 디스크에서 데이터를 읽어오는 작업 中
디스크 컨트롤러가 디스크에서 내용을 읽어 로컬 버퍼에 저장.
저장하는 작업의 완료 여부는 CPU가 체크하는 것이 아닌, 장치의 컨트롤러가 인터럽트 신호 발생하여 CPU에게 전달
📌 컨트롤러들이 CPU의 서비스가 필요할 때 이를 통보하는 방법 = 인터럽트
- 기본적으로 CPU는 매 시점 메모리 명령을 하나씩 읽어와 수행, 이때마다 인터럽트 발생 여부 확인
- 인터럽트가 발생한 경우, CPU 라인 옆에 `인터럽트 라인 (Interrupt Line)`을 통해 하던 작업을 멈추고
인터럽트 관련 작업 처리 - 운영체제의 커널에는 인터럽트가 들어왔을 때 해야 할 일에 대한 코드 보관
- 할 일을 쉽게 찾아가기 위해 인터럽트 종류마다 번호를 정해서, 번호에 따라 처리해야할 코드가 위치한 부분을 가리키고 있는 자료구조 사용 (= 인터럽트 벡터 (Interrupt Vector))
- 실제 처리해야할 코드는 인터럽트 처리 루틴(Interrupt Service Routine) 혹은 인터럽트 핸들러(Interrupt Handler) 라고 불리는 곳에 저장
인터럽트 종류
1. 하드웨어 인터럽트
외부장치나 하드웨어의 동작에 의해 발생하는 인터럽트
CPU외부에서 발생하는 신호에 의해 처리됨
- I/O 인터럽트: I/O 장치의 작업 완료나 오류 발생 시 CPU에 서비스 요청
- 전원 이상 인터럽트: 정전이나 전원 공급의 이상이 있을 때 발생
- 기계 고장 인터럽트: CPU의 기능적 오류나 하드웨어 고장 시 발생
- 외부 신호 인터럽트: 타이버나 사용자의 의도적인 신호에 의해 프로그램 중단되는 경우
2. 소프트웨어 인터럽트
프로그램 내부에서 특정 명령어를 실행하거나 예외 상황이 발생했을 때 소프트웨어적으로 발생하는 인터럽트
주로 트랩(trap)이라는 용어로 불림
- 시스템 호출 (System Call): 응용 프로그램이 운영체제의 서비스를 요청할 때 발생
- 예외 상황 (Exception): 0으로 나누기, 유효하지 않은 명령어 실행 등 프로그램 실행 중 오류 발생 시
3. 마스커블 인터럽트 (Maskable Interrupt)
CPU가 인터럽트의 우선순위에 따라 처리를 지연시킬 수 있는 인터럽트
4. 비마스커블 인터럽트 (Non-Maskable Interrupt)
즉시 처리되어야 하며, CPU에 의해 무시되거나 지연될 수 없는 높은 우선순위의 인터럽트
하드웨어 인터럽트 VS 소프트웨어 인터럽트
구분 | 하드웨어 인터럽트 | 소프트웨어 인터럽트 |
발생 원인 | 외부 하드웨어 장치 | 프로그램 내부에서 발생 |
비마스커블 인터럽트 유/무 | 有 (전원 오류, 치명적 하드웨어 장애) | 無 (OS 제어 가능) |
마스킹 가능 여부 | 일부 가능 (마스커블 인터럽트만) | 가능 (OS 관리 가능) |
소프트웨어 인터럽트 中 예외(Exception)가 비마스커블이 될 순 없나 ❓
예외는 예상치 못한 오류 상황에서 발생함
예외에도 CPU가 반드시 처리해야 하는 것과 무시할 수 있는 것 존재
하지만, 결국 OS에서 핸들링할 수 있기 때문에 `완전한` 비마스커블 인터럽트라고 보기 어려움
∵ `0으로 나누기`의 경우, OS가 이를 처리할지 프로세스를 종료할지 결정
인터럽트 작동 원리
1. 인터럽트 발생
- 하드웨어 요청: 외부장치 (키보드, 마우스 등) 에서 이벤트가 발생하면, 해당 장치의 컨트롤러가 CPU에 인터럽트 요청
- 소프트웨어 요청: 프로그램이 운영체제의 서비스를 요청할 때 발생
즉, 장치 컨트롤러가 인터럽트 요청 (Interrupt Request, IRQ) 신호 전송
이때, 인터럽트 번호 (Interrupt Number 또는 Vector Number) 함께 전달
ex) 타이머 인터럽트 = 0x20번 / 키보드 인터럽트: 0x21번
2. 인터럽트 신호 수신
CPU는 인터럽트 핀인 특정 핀을 통해 인터럽트 신호 수신
해당 신호는 CPU가 현재 작업을 중단하고 인터럽트를 처리해야 함을 알림
3. 현재 상태 저장
CPU는 현재 실행중인 프로그램의 상태 (레지스터, 프로그램 카운터 등)를 스택에 저장 (in PCB)
👉 추후 작업 재개 시 필요
4. 인터럽트 벡터 테이블 조회
- CPU는 인터럽트 번호를 기반으로 인터럽트 벡터 테이블에 접근
- IVT 는 RAM 또는 ROM의 특정 고정된 위치에 존재
5. ISR 실행
해당 인터럽트 벡터가 가리키는 메모리 주소에서 ISR의 실제 물리적 주소를 읽음
- 보통 `세그먼트:오프셋` 형식으로 저장
ex) ISR의 주소가 0X1234:5678, 물리 주소: 0x1234 x16 + 0x5678
CPU가 해당 ISR 코드로 점프하여 실행 시작
ISR 코드로 점프 ❓
CPU가 IVT를 참조해서 ISR 시작 주소를 알아내고, 그 위치로 코드 실행 흐름을 옮긴다는 의
6. ISR 실행 종료, 상태 복원
ISR 끝에는 `IRET(Interrupt Return)` 명령어 존재
이전에 저장한 PC, 레지스터 등을 스택에서 복원하고 원래 작업으로 복귀
인터럽트 벡터 테이블 (Interrupt Vector Table, IVT)
하드웨어 또는 소프트웨어 인터럽트가 발생했을 때
CPU가 어떤 코드 (= ISR, 인터럽트 서비스 루틴) 로 이동해야 하는지를 알려주는 주소 목록이 저장된 테이블
IVT가 필요한 이유
- 유연성: ISR 주소를 테이블에서 나중에 바꿀 수 있음
- 모듈화: 키보드, 마우스, 타이머 등 장치별 ISR을 따로 분리
- 운영체제 제어권 확보: BIOS ISR → OS가 덮어씌워 커스터마이징 가능
- 보안성 & 안정성: 커널이 ISR 제어 가능
IVT 구조 (실모드 기준)
- 위치: 메모리의 0x0000 ~ 0x03FF (1KB), RAM의 가장 앞부분에 존재
- 구조: 256개의 인터럽트에 대해 각각 4byte (2byte: offset + 2byte: 세그먼트)
-> 256 x 4 =1024 byte = 1KB - 내용: 각 인터럽트 번호에 대응하는 ISR의 실제 주소 (세그먼트:오프셋) 저장
ex) 인터럽트 번호 0x21이 발생한 경우
1. CPU는 IVT에서 0x21 x 4 = `0x84` 오프셋 부터 4byte 읽음
2. 그곳에 저장된 세그먼트:오프셋 주소 로 즉시 점프
3. 해당 ISR 실행
실 모드 VS 보호 모드
현대 운영체제는 전부 보호모드 사용
CPU 부팅 시에는 실모드로 시작되지만, OS가 로딩되면 바로 보호모드로 전환
항목 | 실모드 | 보호모드 |
메모리 주소 방식 | 세그먼트:오프셋 (최대 1MB) | 32비트, 64비트 선형 주소, 페이징 가능 |
메모리 보호 | X (모든 코드 모든 영역 접근) | O (프로세스 별 메모리 보호) |
멀티태스킹 | X | O |
예외 처리 | 제한적 | 세밀한 예외, 인터럽트, 페이지 폴트 처리 |
IVT | IVT 고정 (RAM 상단 1KB) | IDT, 위치 자유 + 보안 |
보안성 | 낮음 (모든 코드 하드웨어 제어) | 높음 (커널만 핵심 자원 접근) |
사용 시기 | DOS 시절 (~1990년대 초) | 현대 OS 전부 사용 (Window, Linux 등) |
보호 모드에서 인터럽트 처리 (IVT > IDT)
보호 모드에서는 IDT (Interrupt Descriptor Table)라는 구조 사용
- 인터럽트 번호와 ISR 주소 매핑은 동일
- 구조 & 접근 권한 상이
특징
- 위치: 메모리 어디든 가능 (IDTR 레지스터로 지정)
- 크기: 256개 엔트리 (0~255 인터럽트)
- 구조: 각 엔트리는 8byte 또는 16byte, 세부 권한/ 세그먼트 정보 포함
- 보안: 커널이 IDT 설정, 사용자 모드는 수정 불가
- 역할: 인터럽티 + 예외 처리
- 저장: CPU 내부 레지스터인 IDTR가 위치 & 크기 저장
커널 (Kernel)
- 하드웨어와 응용 프로그램 사이에서 자원을 관리하는 역할
- CPU, 메모리, 디스크, 네트워크, 파일 시스템 등 제어
- 일반 응용 프로그램이 직접 접근 할 수X, `커널 모드`에서만 실행 가능
유저 모드
- 일반 응용 프로그램이 실행되는 모드
- 운영체제의 중요한 자원에 직접 접근 불가
시스템 콜을 통해서만 커널 기능을 사용할 수 있음
웹 브라우저, 게임, 동영상 플레이어 등
일반 사용자 프로그램은 항상 유저 모드에서 실행
커널 모드
- 운영체제가 실행되는 특권 모드
- CPU가 모든 메모리 / 하드웨어 자원에 접근 가능
파일 시스템 접근 : 사용자가 파일을 저장하면, 커널이 디스크에 저장
메모리 할당 : 프로그램이 실행될 때, 커널이 메모리를 할당
시스템 콜
운영체제가 커널에 접근하기 위한 인터페이스이며 유저 프로그램이 운영체제의 서비스를 받기 위해 커널 함수를 호출할 때 사용
프로세스나 스레드에서 운영체제로 요청을 할 때, `시스템콜`과 `커널`을 거쳐 운영체제로 전달됨
시스템 콜을 사용하면, 유저 모드에서 실행되는 프로그램이 커널 모드로 전환되어 하드웨어 자원에 접근하거나 보호된 시스템 기능 사용 가능
즉, 시스템 콜은 사용자 프로그램과 커널 사이의 상호작용을 가능하게 함
시스템 콜 수행 과정
- 사용자 프로그램이 시스템 콜 요청 (read(), wirte() 등)
- 이 함수는 내부적으로 시스템 콜 번호 & 인자를 레지스터에 설정
- `syscall` 명령어 (소프트웨어 인터럽트) 실행
- CPU는 IDT에서 0x80에 해당하는 ISR을 찾아서 커널모드 전환
- 커널의 시스템 콜 핸들러가 시스템 콜 번호 확인 후 해당 함수 실행
- 작업이 끝나면 결과를 레지스터에 담고 사용자 모드 복귀
명령어 | 설명 |
int 0x80 | 전통적인 x86 방식 |
syscall | x86_64 전용, 더 빠름 |
sysenter / sysexit | Intel 고속 시스템 콜 (Window, Linux) |
svc | ARM 아키텍처에서 시스템 콜 |