# 07. 인터럽트

* 인터럽트란?
  * **CPU가 프로그램을 실행하고 있을 때,**  &#x20;

    **입출력 하드웨어 등의 장치나 또는 예외 상황이 발생하여 처리가 필요할 경우** &#x20;

    **CPU에 알려서 처리하는 기술**&#x20;

    > 어느 한 순간 CPU가 실행하는 명령은 하나! 다른 장치와 커뮤니케이션 어떻게?
  * 컴퓨터 구조단 생각해보기
    * PC(program counter)는 (instruction) code 한줄 한줄을 실행하는데 집중
    * 외부 이벤트 처리해야할 때, 정보를 어떻게 처리할까
    * 처리가 끝났다는 것을 OS에 알려주기.<br>
  * OS 코드 레벨로 생각해보기
    * 저장 매체에서 파일을 읽어 들일 때, **blocking상태(event)에 빠진 상태를** &#x20;

      **어떻게 CPU에 끝났다고 알려서 ready 상태** 로 변경? &#x20;

      (이 기술을 interrupt라고 한다)
    * 즉, event 발생 => (인터럽트) => 처리(kernel code)
    * (현재 사용 중인 사용자 프로그램을 잠시 멈추고, CPU의 제어권을 운영체제로 양도한다)<br>
  * **예외 상황 핸들링**
    * CPU가 프로그램을 실행하고 있을 떄, 입출력 하드웨어 등의 장치 또는 예외 상황 발생한 경우 CPU가 해당 처리를 할 수 있도록 CPU에 알려 줘야 함.
    * **0으로 나누는 연산과 같은 예외 발생 상황**도, CPU는 처리를 하려고 한다.  &#x20;

      그래서 문제가 생길 수 있다. 이런 **예외 상황을 운영체제, 스케쥴러에 알려서** &#x20;

      **프로세스를 kill(error 메세지 발생)** 해야 한다. 이 때 정보를 알려 주는 것을 인터럽트라고 할 수있다.<br>
  * 선점형 스케쥴러에서 사용되는 방법
  * 이벤트를 정의하고, 발생했을 때 처리하는 것을 인터럽트라고 한다.
  * 인터럽트는, 일종의 이벤트로 불린다.
  * 이벤트에 맞게 운영체제가 처리하도록 구현되어있다.<br>

* 인터럽트 종류
  * **내부 인터럽트(trap, sw인터럽트)**
    * 주요 프로그램 내부에서 잘못된 명령(예외 상황) 또는 잘못된 데이터 사용 시 발생
    * 주로 프로그램 내부에서 발생하므로, **소프트웨어 인터럽트**라고도 함
      * **Divide-by-Zero Interrupt:** 0으로 나누는 코드 실행 시&#x20;
      * 사용자 모드(user mode)에서 허용되지 않는 명령 또는 공간 접근 시
        * C언어에서 pointer가 가리키는 주소가 잘못됬을 때
          * Linux에서 0-4GB를 '프로세스'공간이라고 함. 이 때,&#x20;
          * 0-3GB는 user mode
          * 3-4GB를 kernel mode라고 함.
          * 사용자 모드에서 process로 실행하다가, 포인터가 kernel모드를 가리켰을 때 에러 발생
      * 계산 결과가 Overflow/Underflow 날 때
        * int 변수 type 지정시, 32bit
          * unsigned(부호 없는 것)
          * signed(부호 있는 것) (2³¹만큼 수 표현)
            * 이 때 1 bit는 부호를 표시함.
            * 2³¹ + 2³¹ => overflow
            * (컴구에서 overflow본것 다시 정리)
            * 음수로 표현 가능한 범위를 벗어난 경우 =>underflow
  * **외부 인터럽트(hw인터럽트)**:&#x20;
    * 주로 하드웨어에서 발생되는 이벤트(프로그램 외부)
    * 주로 하드웨어에서 발생하므로, **하드웨어 인터럽트**라고도 함.
      * 전원 이상
      * 기계 문제
      * **I/O 관련 이벤트**: 프린터, 마우스, 키보드, 저장 매체(SSD등)
      * **timer interrupt**: 선점형 스케쥴러 위해 필요
        * H/W로 부터 일정시간마다 타이머 인터럽트를 OS(kernel모드)에 알려줌
        * 일정 시간마다, process를 교체하겠다.

* 인터럽트 내부 동작
  * 시스템콜 인터럽트
    * 시스템콜 실행을 위해서는 강제로 코드에 인터럽트 명령을 넣어, CPU에게 실행 시켜야 한다.
    * 시스템 콜 실제 코드(어셈블리어\_인텔기준)
      * eax 레지스터에 시스템 콜 번호를 넣고,
      * ebx 레지스터에 시스템 콜에 해당하는 인자 값을 넣고,
      * 소프트웨어 인터럽트 명령을 호출하면서 0 X 80 값을 넘겨줌.
        * 여기서 쓰인 int = interrupt

          ```
          mov eax, 1
          mov ebx, 0
          int 0 X 80
          ```
    * 시스템 콜 인터럽트 명령을 호출하면서, 0X80 값을 넘겨줌
      * CPU는 사용자 모드를 커널 모드로 바꿔줌
      * IDT(Interrupt Descriptor Table)에서 0 X 80에 해당하는 주소(함수) 찾아 실행 &#x20;

        \[interrupt 번호 : 주소(함수 코드)]
      * system\_call()함수에서 eax로부터 시스템 콜 번호를 찾아서, 해당 번호에 맞는 시스템콜 함수로 이동 &#x20;

        \[시스템콜번호: kernel function(system call)]
      * 해당 시스템콜 함수 실행 후, 다시 커널 모드에서 사용자 모드로 변경하고, 다시 해당 프로세스 다음 코드 실행
  * 인터럽트와 IDT
    * 인터럽트는 미리 정의되어 각각 번호와 실행 코드를 가리키는 주소가 기록되어있다.
      * 어디에? IDT(Interrupt Descriptor Table)에 기록
      * 언제? 컴퓨터 부팅 시 운영체제가 (테이블을) 기록
      * 어떤 코드? 운영체제 내부 코드
    * 정리
      * 항상 인터럽트가 발생하면, IDT(Interrupt Descriptor Table)을 확인한다.
      * 시스템콜 인터럽트 명령은 0X80 번호가 미리 정의.
      * 인터럽트 0X80 에 해당하는 운영체제 코드는 system\_call()이라는 함수
      * 즉 IDT에는 0X80 => system\_call()과 같은 정보가 기록되어있음.
    * 리눅스 예
      * 0\~31: 예외상황 인터럽트(내부/소프트웨어 인터럽트)&#x20;
        * 일부는 정의 안된 채로 남겨져 있음
      * 32\~47: 하드웨어 인터럽트(주변장치 종류/갯수따라 변경가능)
      * 128: 10진수로 0X80을 표현

* 인터럽트와 프로세스 정리
  * 프로세스 실행 중, 인터럽트 발생
  * 현 프로세스 실행 중단
  * 인터럽트 처리 함수 실행(운영체제, 커널 모드)
  * 현 프로세스 재 실행

* 선점형 스케쥴러 예시
  * 수시로 timer interrupt가 발생
    * OS 가 timer interrupt횟수를 기억했다가 예를 들어 5번 이상 발생한다면 현재 프로세스 중지하고, 다른 프로세스 실행한다.&#x20;
