인터럽트
인터럽트란?
- CPU가 프로그램을 실행하고 있을 때 입출력 하드웨어 등의 장치나 예외 상황이 발생하여 처리가 필요할 경우에 CPU가 알려서 처리하는 기술
어떤 한 순간에 CPU가 실행하는 명령은 하나인데 다른 장치와 어떻게 통신을 할까?
인터럽트 필요 이유
- 선점형 스케쥴러 구현
- 프로세스 running 중에 스케쥴러가 이를 중단시키고 다른 프로세스로 교체하기 위해 현재 프로세스 실행을 중단시킴 -> 그러려면 스케쥴러 코드가 실행이 되어 현 프로세스 실행을 중지해야 함
- I/O Device와의 커뮤니케이션
- 저장매체에서 데이터 처리 완료 시 프로세스를 깨워야 함 (blocked -> ready)
- 예외 상황 핸들링
- CPU가 프로그램을 실행하고 있을 때 입출력 하드웨어 등의 장치나 예외상황이 발생할 경우 CPU가 해당 처리를 할 수 있도록 CPU에 알려줘야 함
인터럽트 처리 예
- CPU가 프로그램을 실행하고 있을 때
- 입출력 하드웨어 등의 장치 이슈 발생
- 파일 처리가 끝났다는 것을 운영체제에 알려주기
- 운영체제는 해당 프로세스를 blocked state에서 ready 상태로 프로세스 상태 변경
- 또는 예외 상황이 발생
- 0으로 나누는 계산이 발생해서 예외 발생을 운영체제에 알려주기
- 운영체제가 해당 프로세스 실행 중지/에러 표시
- 입출력 하드웨어 등의 장치 이슈 발생
인터럽트의 종류
이벤트와 인터럽트
- 인터럽트는 일종의 이벤트로 이벤트에 맞게 운영체제가 인터럽트를 처리
주요 인터럽트
- 계산하는 코드에서 0으로 나누는 코드 실행 (Divide-by-Zero Interrupt)
#include <stdio.h>
int main()
{
printf("Hello World!\n");
int data;
int divider = 0;
data = 1 / divider; // 이 부분에서 인터럽트 발생. 컴파일러가 잡아내지 못하는 에러
return 0;
}
타이머 인터럽트
선점형 스케쥴러를 위해 필요, 하드웨어로부터 일정 시간마다 타이머 인터럽트를 운영체제에 알려줌
입출력(I/O) 인터럽트: 프린터, 키보드, 마우스, 저장매체
인터럽트 종류
- 내부 인터럽트: 주로 프로그램 내부에서 잘못된 명령 또는 잘못된 데이터 사용시 발생, 소프트웨어 인터럽트
- 0으로 나눴을 때
- 사용자 모드에서 허용되지 않은 명령 또는 공간 접근시 (커널 모드에 할당된 공간 접근 등)
- 계산 결과 Overflow/Underflow 발생
- 외부 인터럽트: 주로 하드웨어에서 발생하는 이벤트 (프로그램 외부), 하드웨어 인터럽트
- 전원 이상
- 기계 문제
- 키보드 등 I/O 관련 이벤트
- Timer 이벤트
인터럽트 내부 동작
시스템 콜 인터럽트
- 시스템 콜 실행을 위해서는 강제로 코드에 인터럽트 명령을 넣어 CPU가 실행해야 한다.
- 시스템 콜 실제 코드
mov eax, 1 // 시스템 콜 번호를 eax 레지스터에 넣음 (ex. open -> 1)
mov ebx, 0 // 시스템 콜에 해당하는 인자값을 ebx에 넣음
int 0x80 // int: CPU op code, 소프트웨어 인터럽트 명령
인터럽트와 시스템 콜
- 시스템 콜 인터럽트 명령을 호출하면서 0x80 값을 넘겨줌
- CPU는 사용자 모드를 커널 모드로 전환
- IDT(Interrupt Descriptor Table)에서 0x80에 해당하는 주소(함수)를 찾아서 실행함
- system_call() 함수에서 eax로부터 시스템 콜 번호를 찾아서 해당 번호에 맞는 시스템 콜 함수로 이동
- 해당 시스템 콜 함수 실행 후 다시 커널 모드에서 사용자 모드로 변경하고 다시 해당 프로세스 다음 코드 진행
사용자/커널 모드와 프로세스, 인터럽트
인터럽트와 IDT
- 인터럽트는 미리 정의되어 각각 번호와 실행 코드를 가리키는 주소가 기록되어 있음
- IDT(Interrupt Descriptor Table)에 컴퓨터 부팅시 운영체제가 운영체제 내부 코드에 기록
- 발생 예시
- 인터럽트 발생 시 IDT를 확인
- 시스템 콜 인터럽트 명령은 0x80 번호가 미리 정의
- 인터럽트 0x80에 해당하는 운영체제 코드는 system_call() 이라는 함수
- IDT에는 0x80 -> system_call()과 같은 정보가 기록되어 있음
- 리눅스의 예
- 0-31: 예외 상황 인터럽트 (일부는 정의 안된 채로 남겨져 있음)
- 32-47: 하드웨어 인터럽트 (주변장치 종류/갯수에 따라 변경 가능)
- 128: 시스템 콜
인터럽트와 프로세스
- 프로세스 실행 중 인터럽트 발생
- 현 프로세스 실행 중단
- 인터럽트 처리 함수 실행 (운영체제)
- 현 프로세스 재실행
인터럽트와 스케쥴러
- 선점형 스케쥴러의 구현 예시
- 운영체제가 타이머 인터럽트 발생 횟수를 기억해서 타이머 인터럽트가 5번 발생하면 현재 프로세스를 다른 프로세스로 전환