CS/Operating System

인터럽트와 입출력 방식

olsohee 2024. 4. 6. 18:03

인터럽트

CPU는 특별한 일이 없으면 현재 수행 중인 프로세스의 다음 명령을 순차적으로 수행한다. CPU는 매번 프로그램 카운터가 가리키는 곳에 있는 명령어를 수행한다. 따라서 현재 수행 중인 프로세스로부터 CPU를 회수해서 CPU가 다른 일을 수행하도록 하기 위해서는 인터럽트가 필요하다.

특권 명령

특권 명령은 운영체제 내에서 특정한 권한이 필요한 명령어를 말한다. 따라서 특권 명령을 실행하기 위해서는 일반 사용자 프로그램이 실행하는 것은 불가하고 인터럽트를 발생시켜 운영체제만 특권 명령을 실행할 수 있다. 즉, 모드 비트가 0일 때(=커널 모드)만 특권 명령을 실행할 수 있다.

인터럽트의 종류(발생 상황)

인터럽트는 인터럽트를 발생시키는 주체가 누구냐에 따라 하드웨어 인터럽트와 소프트웨어 인터럽트로 나뉜다. 

  • 하드웨어 인터럽트: 장치 컨트롤러와 같은 하드웨어 장치가 인터럽트 라인을 세팅한다. 본질적인 의미의 인터럽트이다.
  • 소프트웨어 인터럽트(트랩): 사용자 프로그램과 같은 소프트웨어가 인터럽트 라인을 세팅한다.
    • 예외 상황(exception): 사용자 프로그램이 0으로 나누는 연산과 같이 비정상적인 작업을 시도하거나, 자신의 메모리 영역 바깥에 접근하려는 시도 등 권한이 없는 작업을 시도할 때 이에 대한 처리를 위해 발생시키는 인터럽트를 말한다.
    • 시스템 콜: 사용자 프로그램이 운영체제의 커널 함수를 호출하는 것을 의미한다. 

인터럽트 백터와 인터럽트 처리 루틴(인터럽트 핸들러)

  • 인터럽트 백터: 인터럽트의 종류에 따라 그 처리 방법이 다르다. 인터럽트 벡터는 해당 인터럽트의 처리 루틴 주소를 가지고 있다. 즉, 인터럽트 종류마다 번호를 정해서 번호에 따라 처리해야 할 코드가 위치한 부분을 가리키고 있는 자료구조이다.
  • 인터럽트 처리 루틴: 해당 인터럽트를 처리하는 커널에 정의된 코드이다.

인터럽트 발생과 처리 흐름

  1. CPU는 매번 프로그램 카운터가 가리키고 있는 명령어를 수행하고, 다음 명령을 수행하기 직전에 인터럽트 라인이 세팅되었는지 확인한다.
  2. 인터럽트가 발생했으면 CPU는 현재 수행하던 프로세스를 중단하고, 그 정보를 PCB에 저장한다.
  3. 그리고 운영체제에게 CPU의 제어권이 넘어가며, 운영체제의 인터럽트 처리 루틴으로 이동해서 인터럽트를 처리한다.
  4. 인터럽트 처리를 마친 후에는 인터럽트가 발생하기 직전의 프로세스에게 CPU 제어권이 다시 넘어간다.

인터럽트 우선순위

만약 인터럽트 처리 중에 또 다른 인터럽트가 발생하면 어떻게 될까? 이 경우 일반적으로 우선 순위가 높은 인터럽트가 먼저 처리된다. 

  1. 현재 CPU가 처리 중인 인터럽트보다 우선 순위가 높은 새로운 인터럽트가 발생하면, 현재 처리 중인 작업을 일시 중단하고 수행 중이던 인터럽트 코드의 수행 지점을 저장한다.
  2. 우선순위가 높은 새로운 인터럽트를 처리한다.
  3. 새로운 인터럽트의 처리가 끝나면 저장된 주소로 복귀해 이전에 수행하던 인터럽트 처리 코드를 마저 수행한다.

입출력 방식

입출력(I/O)이란 컴퓨터 시스템이 컴퓨터 외부의 입출력 장치들과 데이터를 주고받는 것을 말한다. 입출력 방식에는 동기식 입출력과 비동기식 입출력이 있다.

동기식 입출력(Synchronous I/O)

동기식 입출력은 어떤 프로그램이 입출력을 요청했을 때 입출력 작업이 완료된 후에야 그 프로그램이 후속 작업을 진행하는 방식이다. 동기식 입출력 방식은 두 가지가 있다.

  • I/O 작업이 진행되는 동안 해당 프로그램의 다음 작업을 수행하지 않고 I/O 작업이 완료되어 인터럽트가 발생할 때까지 기다리는 방식. 그러나 이 방식은 느린 I/O 작업이 끝날 때까지 CPU가 인터럽트를 기다리며 일을 하지 않기 때문에 매우 비효율적이다.
  • 따라서 일반적으로 I/O 작업을 수행 중인 경우 CPU를 다른 프로그램에게 넘겨 CPU가 계속 쉬지 않고 명령을 처리할 수 있도록 한다. 예를 들어, 프로그램 A가 CPU를 할당받고 명령을 수행하다가 입출력 요청을 하게 되면, CPU를 프로그램 A에게서 빼앗아 프로그램 B에게 할당하여 B의 명령을 수행하고, 프로그램 A의 입출력이 완료될 때까지 A에게는 CPU를 할당하지 않는다. 이때 A는 프로그램의 상태를 봉쇄 상태로 전환시킨다. 봉쇄 상태의 프로그램에게는 CPU를 할당하지 않는다. 그런데 어떤 프로그램이 입출력 연산을 수행 중일 때 CPU가 다른 프로그램의 명령을 수행하면, 다수의 I/O 연산이 동시에 요청될 수 있다. 따라서 I/O 작업을 순차적으로 처리하기 위해 장치마다 큐를 두어, 요청 순서대로 I/O 작업을 수행한다. 즉, 순차적으로 요청을 처리함으로써 동기화 문제를 해결한다. 

동기식 입출력 방식의 흐름은 다음과 같다.

  1. 프로그램 A가 실행 중에 디스크에 어떤 데이터를 읽어오는 명령을 만나면, 프로그램 A는 시스템 콜을 통해 (소프트웨어) 인터럽트를 발생시켜 운영체제에게 입력을 요청한다.
  2. CPU는 지금까지 A의 코드를 실행하던 일을 멈추고 현재 상태(코드의 메모리 주소, 레지스터 값, 하드웨어 상태 등)를 PCB에 저장한다.
  3. CPU의 제어권은 운영체제에게 넘어가고, 운영체제의 인터럽트 처리 루틴에 따라 인터럽트를 처리한다.
    1. 운영체제는 컨트롤러에게 입력 연산을 요청한다. 즉  입출력 장치의 큐에 입력 요청을 줄세운다.
    2. 컨트롤러는 A가 요청한 데이터를 읽어 들어오며 이를 로컬버퍼에 저장한다.
  4. 입력 장치 컨트롤러가 데이터를 읽어오는 동안 프로그램 A는 봉쇄 상태이며, 따라서 CPU를 할당받지 못한다.
  5. 그동안 CPU는 다른 프로그램인 B에게 할당해 B의 명령을 수행한다.
  6. 원하는 정보가 로컬버퍼로 다 들어오면 컨트롤러는 (하드웨어) 인터럽트를 발생시켜 CPU에게 입출력이 완료됐음을 알린다. 
  7. 프로그램 B를 수행 중이던 CPU는 B의 실행 상태를 저장해놓고 인터럽트를 처리한다.
    1. 로컬버퍼에 있는 데이터를 A의 메모리 영역으로 읽어오고, A의 봉쇄 상태를 해제시킨다.
    2. 그리고 A는 다시 CPU를 기다리는 줄에 서게 된다.
  8. 그 후 원래 수행하던 프로그램 B를 마저 수행한다.
  9. 프로그램 A는 CPU를 기다리는 줄에서 기다리다가 자신의 차례가 되면 CPU를 할당받고 입출력 연산 이후의 작업을 수행한다.

비동기식 입출력(Asynchronous I/O)

비동기식 입출력은 입출력 연산 요청 후에 연산이 끝나기를 기다리는 것이 아니라 CPU의 제어권을 입출력 연산을 호출한 그 프로그램에게 곧바로 다시 부여하는 방식이다. 어떤 프로그램에 데이터를 읽어오라는 요청을 했을 때 읽어온 결과를 활용해서 다음 연산을 수행하는 경우도 있지만, 읽어온 데이터와 관계없이 수행하는 연산도 있다. 입출력 연산과 동시에 읽어오는 데이터와 관련 없는 명령이 먼저 수행된다. (ex, 출력 장치에 데이터를 쓰는 요청의 경우, 쓰기 작업이 완료되기 전에 다음 명령을 수행할 수 있기 때문에 이 경우 비동기식 입출력이 사용될 수 있다.) 읽어오는 데이터가 필요한 연산은 입출력이 완료된 후에 수행된다.

 

비동기식 입출력 방식의 흐름은 다음과 같다.

  1. 입출력 연산 수행 중에도 CPU의 제어권은 입출력을 요청한 프로세스에게 주어진다.
  2. CPU는 입출력 연산과 무관하게 처리할 수 있는 명령부터 처리한다.
  3. 입출력 연산이 끝나면 인터럽트를 통해 완료됨을 CPU에게 알린다.
  4. CPU는 읽어온 데이터를 필요로 하는 명령을 이제 수행할 수 있다.

일반적으로 입력의 경우 입력된 데이터를 이용한 작업이 이어지기 때문에 입출력이 완료될 때까지 해당 프로그램을 봉쇄시키는 동기식 입출력이 사용된다. 그러나 출력과 같이 입출력 연산과 뒤에 이어지는 작업이 무관한 경우에는 비동기식 입출력을 사용할 수도 있다.


Reference

  • 이화여자대학교출판문화원, 운영체제와 정보기술의 원리, 반효경