개념공부/컴퓨터구조와 운영체제

04장 - 3 : 명령어 사이클과 인터럽트

Cadi 2025. 4. 3. 01:53

 

목표 : 하나의 명령어를 처리하는 흐름인 명령어 사이클과 , 그 흐름을 방해하는 인터럽트 학습

 

CPU가 하나의 명령어를 처리하는 과정에는 특정한 흐름이 있고, 그 흐름을 명령어 사이클이라고 한다.

명령어 사이클을 반복해가며 나아가다 흐름이 끊기는 상황을 인터럽트라고 한다. 

 

 

명령어 사이클

 

명령어들이 일정한 주기로 반복되며 실행되는 것, 다음 세 가지 사이클이 있다.

  • 인출 사이클 : 메모리에 있는 명령어를 CPU로 가져오는 단계
  • 실행 사이클 : CPU로 가져온 명령어를 실행하는 단계, 명령어를 해석하고 제어 신호를 발생시킨다.
  • 간접 사이클 : 간접 주소 지정 방식으로 인해 메모리에 접근을 한 번 더 해야 하는 경우
                          즉, 명령어에 피연산자가 직접적으로 포함되지 않고, 해당 피연산자의 주소만 포함되어 있는 경우
                          한 번 더 메모리에 접근에 실제 피연산자 값을 가져오는 과정

 

인터럽트

 

CPU가 실행 중인 명령어를 수행하던 도중, 예기치 않은 요청이나 이벤트로 인해 실행 흐름이 변경되는 것.

인터럽트가 발생하면 CPU는 현재 작업을 저장하고 새로운 요청을 처리한 뒤 원래 작업으로 복귀한다.

  • 동기 인터럽트 : CPU에 의해 발생되는 인터럽트, 예외(exception)이라고 부른다.
                             현재 실행중인 명령어의 실행 결과에 의해 발생하는 인터럽트. 
  • 비동기 인터럽트 : 주로 입출력 장치에 의해 발생되는 인터럽트, 하드웨어 인터럽트라고 불리기도 한다.
                                  현재 실행중인 명령어와는 무관하게 외부 하드웨어 장치 등에 의해 발생하는 인터럽트.

동기 인터럽트

 

예외의 종류에는 폴트, 트랩, 중단, 소프트웨어 인터럽트가 있다. 

  • 폴트 : 예외를 처리한 직후 예외가 발생한 명령어부터 실행을 재개하는 예외
  • 트랩 : 예외를 처리한 직후 예외가 발생한 다음 명령어부터 실행을 재개하는 예외 (예 :디버깅을 위한 브레이킹 포인트)
  • 중단 : CPU가 프로그램을 강제로 중단시킬 수밖에 없는 오류를 발견했을 때 발생하는 예외 (Abort ) (예 : 메모리 손상)
  • 소프트웨어 인터럽트 : 시스템 호출이 발생했을 때 나타나는 예외

비동기 인터럽트

 

CPU가 주기적으로 입출력 장치의 상태를 확인하는 것이 아닌, 비동기 인터럽트를 통해 완료 여부를 판단함으로써 

비동기 인터럽트(하드웨어 인터럽트)는 입출력 작업 중에도 CPU로 하여금 효율적으로 명령어를 처리할 수 있게 한다.

 

비동기 인터럽트의 처리 순서는 다음과 같다 .

  1. 입출력장치가 CPU에 인터럽트 요청 신호를 보낸다. 
  2. CPU는 실행 사이클이 끝나고 명령어를 인출하기 전에 항상 인터럽트 여부를 확인한다.
  3. CPU는 인터럽트 요청을 확인하고 인터럽트 플래그를 통해 현재 인터럽트를 받아들일 수 있는지 여부를 확인한다.
  4. 인터럽트를 받아들일 수 있다면 , CPU는 지금까지의 작업을 백업한다.
  5. CPU는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행한다. 
  6. 인터럽트 서비스 루틴이 끝나면 백업해둔 작업을 복구하여 실행을 재개한다. 

여러 개의 요청 신호(IRQ, interrupt Request)가 들어온다면, 인터럽트 우선순위를 정해서 처리한다. 

 

모든 비동기 인터럽트를 인터럽트 플래그로 막을 수 있는 것은 아니다. 

무시할 수 없는 비동기 인터럽트가 존재한다, 예를 들어 정전이나 하드웨어 고장으로 인한 인터럽트가 해당된다. 

예를 들어 CPU가 특정 중요한 작업 ( 인터럽트 서비스 루틴 실행 중)에 있을 때는 인터럽트 플래그가 활성화 되어 있어서

요청이 들어와도 즉시 처리되지 않고, CPU가 다시 인터럽트 가능 상태가 될 때까지 대기해야 한다.

 

인터럽트 서비스 루틴( 인터럽트 핸들러)는 예를 들어,  '마우스가 어떤 인터럽트 요청을 보냈을 때 어떻게 작동한다'처럼

어떤 인터럽트가 발생했을 때 해당 인터럽트를 어떻게 처리하고 동작해야 하는지에 대한 정보로 이루어진 프로그램이다.

메모리에는 여러개의 인터럽트 서비스 루틴이 저장되어 있는데 이 주소를 구분하기 위해 비동기 인터럽트 요청을 보낼 때

서비스 루틴의 주소인 인터럽트 벡터를 함께 보내게 된다. 

 

서비스 루틴이 실행되기 전에 프로그램 카운터 값 등 현재 프로그램을 재개하기 위해 필요한 모든 내용을 스택에 백업한다.

 

 

 

 

 

 

질문 : 마우스/키보드는 입력이 굉장히 많을 텐데 계속 인터럽트를 발생시키는가 ?

 

마우스, 키보드는 입력이 굉장히 많을텐데 매 번 인터럽트를 발생시키고, 백업을 하고 실행하고 다시 재개하는 과정을

계속해서 반복하는 것은 비효율적이지 않을까 ? 클리커 게임 등을 만나면 일초에도 여러 번 CPU의 실행이 중단되는 것인가 ?

 

답변 : 

마우스와 키보드는 사용자의 입력이 있을 때만 하드웨어 인터럽트를 발생시킨다.

하지만 입력이 많다고 무조건 매번 CPU 실행을 중단하는 것은 아니다. 

  • 키보드나 마우스는 사용자가 입력할 때 IRQ를 발생시킨다. 
  • 운영체제는 인터럽트를 받고 나서 버퍼(Queue)를 사용하여 여러 입력을 모아둔 후 한번에 처리 가능하다. 

예를 들어 클리커 게임의 경우, 초당 수십 ~ 수백 번의 클릭이 발생할 것이고, 매번 CPU가 중지된다면 성능 문제가 발생,

이를 방지하기 위해 폴링(CPU가 주기적으로 입력 장치의 상태를 확인)과 인터럽트를 적절히 조합해서 사용한다.

 

질문 : 인터럽트 플래그가 '불가능'이라면 '가능'으로 바뀔때까지 인터럽트 요청이 대기되는 것인가 ?

 

인터럽트 요청이 보내졌을 때, 인터럽트 플래그가 '불가능'이라면 계속해서 대기하는 것인가 ? 

또한 명령어를 실행하다 플래그 레지스터의 인터럽트 플래그가 바뀌는 구체적인 예시를 알고 싶었다. 

 

질문을 쓰고 위의 내용을 보충하는 과정에서 어느정도 해결되었다. 

인터럽트 요청은 대기하다가, IF(Interrupt Flag)가 비활성화 된다면 그 때 다시 요청을 처리한다. 

 

질문 : 컴퓨터가 실행되면 자동으로 연결되어 있는 입출력 장치의 서비스 루틴을 메모리에 할당하는 것인가 ?

 

우리는 기본적으로 키보드/마우스/헤드셋/모니터 등 다양한 입출력 장치를 사용한다. 

이 때 자동으로 연결된 프로그램이 실행되면서 서비스 루틴을 메모리에 저장하는 것인가 ? 

그래서 아무것도 하지 않아도 메모리에 일정 부분 할당된 것들이 있던 것인가 ? 

 

답변 : 

컴퓨터가 부팅될 때 기본적인 입출력 장치의 서비스 루틴이 자동으로 메모리에 로드된다. 

 

질문 : 왜 스택에 백업하는가 ? 

 

답변 : 

1. 현재 실행중인 명령어의 상태를 유지하기 위해 PC의 값과 레지스터 값을 저장한다.

2. 다중 인터럽트의 처리를 위해, 예를 들어 하나의 인터럽트가 실행중인데 우선순위가 더 높은 인터럽트가 발생한다면

스택을 사용해 기존 인터럽트의 상태를 저장하고, 새 인터럽트를 실행한 후 원래 상태로 복구가 가능하다.

3. 컨텍스트 스위칭을 위해, 멀티태스킹 환경에서는 CPU가 여러개의 프로세스를 실행하면서 빠르게 전환해야 한다,

이때 스택을 활용한다면 매끄러운 전환이 가능하다.