본문 바로가기

CS/운영체제

Run 중에 Interrupt가 된다면?

Interrupt되는 순간과, Wating으로 상태변화 되는 순간 전부 Context Switching이 일어난다라고 설명을 했었던 기억이 있다. 하지만, 고작 keyboard, mouse 이벤트로 Context Switching이 일어날수 없지 않을까?



Interrupt란?

일단 Interrupt라는 것을 설명해보도록 하겠습니다. Interrupt는 외부 또는 내부 이벤트인 하드웨어 신호 또는 시스템 콜과 같은 것들로 인해 실행중인 프로세스를 일시 중단하는 것을 의미합니다. Interrupt 신호는 하드웨어 장치인 키보드, 마우스, 디스크, 타이머가 CPU에 보내는 신호입니다. 이러한 신호를 감지하게 되면 CPU는 일단 현재 작업을 중단하게 될 것입니다. 그 이후 인터럽트 벡터 테이블(Interrupt Vector Table, IVT)를 참조하게 되며, 해당 인터럽트의 핸들러 주소를 찾아 실행하게 됩니다.

Interrupt Vector Table 이란?

IVT라고 불리죠. 이는 컴퓨터 메모리 내 특정 위치에 저장된 테이블 입니다. 저는 처음에 커널에 있다고 생각을 했었는데, 커널에 존재하지는 않습니다. 커널에 존재할것이라고 추측한 이유는 Interrupt Service Routine이라는 'ISR(Interrupt Service Routine)이 커널에 존재하고 있다'라고 알고 있어서 그렇게 추측을 했었는데, 실제로는 메인 메모리에 존재한다고 합니다. CPU 메모리 공간 내의 특정 위치(애매한 부분에서 확인 가능 : CPU가 접근할 수 있는 메모리 영역을 매핑한 부분을 뜻함)에서 하드웨어적으로 관리가 되고있습니다. CPU 메모리 공간 내라는 것은 CPU가 접근할 수 있는 메모리 영역을 의미합니다.

어쨌든, 이를 통해서 CPU는 발생한 인터럽트에 맞는 서비스 루틴의 주소를 참조해서 해당 루틴을 실행할 수 있을 것 입니다.

Interrupt Handler 실행 과정

CPU가 현재 작업을 중단하고, 인터럽트 핸들러로 점프하게 됩니다. 커널은 인터럽트 핸들러를 실행하게됩니다. 인터럽트 핸들러라는 것은 특정 인터럽트가 발생했을 때 수행해야하는 작업을 정의한 코드라고 말할 수 있습니다.  이러한 핸들러는 인터럽트의 원인을 처리하게 되고, 이 과정에서 필요한 경우 PCB에 일부 정보를 저장하기도 합니다. 이런것은 시스템 콜에 의한 인터럽트 일때 발생하게 됩니다. 이러한 실행이 종료되면, 저장된 레지스터 값이 복원되고 원래의 작업이 재개될 것입니다. 이러한 복원 작업은 Interrupt Stack과 CPU의 명령어를 통해서 이루어지게 됩니다.

Interrupt Stack 이란?

인터럽트 처리 과정에서 사용하는 스택 메모리 공간을 의미합니다. CPU가 인터럽트를 처리하기 위해선 현재 작업 상태를 보존해야 하며, 이를 위해 Interrupt Stack 메모리에 중단된 작업의 컨텍스트인 레지스터 값, 프로그램 카운터를 저장하게 됩니다. 제 생각에는 CPU의 스택 포인터가 원래 프로세스의 Stack을 가리키다가, Interrupt Stack을 가리키게 되지 않을까 생각이 됩니다. 이러한 ISR 전용 스택을 별도로 설정해서 일반 작업 스택과 분리해서 관리를 하게 됩니다.(물론 일부 시스템에서 적용입니다.)

인터럽트 스택의 구조에 대해서 설명해보겠습니다.

인터럽트 처리 과정에서 CPU가 필요한 데이터를 저장하고 복구하기 위해 사용하는 공간입니다. 특히, 인터럽트가 발생하게 되면 CPU는 현재 실행 중인 작업 상태를 Interrupt Stack에 저장을 하게 됩니다. 그 후, ISR을 실행하게 되고, ISR이 종료되면 스택에서 해당 데이터를 복구하게 됩니다. 이러한 작업을 보면, Interrupt Stack은 어떤 데이터를 갖고 있을 것입니다.

  • 일단 PC를 갖고 있게 될것입니다. ISR이 끝난 후에 복귀할 때 사용이 될 것입니다.
  • 프로세서 플래그를 갖고 있을 것 입니다. 인터럽트 발생 시 CPU의 상태, 그리고 복귀 시 동일한 CPU 상태를 복구하기 위해 저장되어 있습니다.
  • 레지스터가 저장될 것입니다. 일반적으로 EAX, EBX, ECX, EDX 등이 저장될 것이고, 이는 중단된 프로그램의 실행 상태를 보존하기 위함이 될 것입니다.
  • ISR 실행을 위한 스택 공간에 ISR에서 사용되는 로컬 변수나 데이터, 이 공간은 호출된 ISR에 의해 동적으로 추가 될 것입니다.


Interrupt Stack이라는 것은 ISR도 함수란 소리일까?


일단 ISR은 당연히 코드일 것입니다. 어떤 실행을 처리하는 것이니까요? ISR(Interrupt Service Routine)에 대해서 설명해보겠습니다. 일단 커널에 저장되어 있습니다. ISR은 일반적으로 운영체제의 커널 내에 포함되어 있고, 리눅스는 ISR이 커널 모듈 또는 드라이버의 일부로 구현되어 있습니다.

ISR은 가능한 빠르고 효율적으로 인터럽트를 처리해야하기 때문에, 일반적으로 수행 시간이 짧고 간단한 작업으로 제한됩니다. 그래서 CPU가 빠르게 처리를 할 수도 있고, 복잡한 작업이 수반된 내용이라면? 커널에서 처리를 할 수도 있습니다. (I/O 작업이 필요하다면?)

그런데 실제로 Context Switching도 발생할 수 있잖아?

만약 현재 프로세스가 I/O를 기다리며 대기(wait) 상태로 전환되는 경우가 있습니다. 그리고 HDD나 SSD에 접근하게 되는 경우죠. 그때 현재 프로세스가 대기 상태로 전환되면 CPU는 다른 준비된 프로세스를 실행하게 됩니다.

타임 슬라이스가 만료되었다면? 멀티태스킹 시스템에서는 각 프로세스가 CPU를 사용할 수 있는 시간 타임 슬라이스가 존재하게 되는데, 타임 슬라이스가 만료되면 타이머 인터럽트가 발생됩니다. 그리고 운영체제가 현재 프로세스의 상태를 저장하고 다른 준비된 프로세스(Ready Queue에 있는)로 전환합니다.

  • 명시적으로 시스템 호출 함수를 사용하게 된다면? Sleep, yield와 같은 것이 존재하고 프로세스가 시스템 호출을 통해 스스로 CPU 사용을 포기하는 경우가 있습니다. 프로세스 상태가 대기로 전환되면서 Context Switching이 발생하게 됩니다.
  • 우선 순위가 변경이 된다면? 높은 우선순위의 프로세스가 실행 준비 상태가 되면, 현재 프로세스를 선점하고 Context Switching이 발생하게 됩니다.
  • 프로세스가 종료된다면? 프로세스가 종료되면 운영체제는 이를 프로세스 테이블에서 제거하고, 준비 상태의 다른 프로세스를 선택해 실행하게 됩니다.

Context Switching과 Interrupt의 관계는 Interrupt Handling은 Context Switching이 아닙니다. 또한, Interrupt 는 항상 Context Switching으로 이어지지 않습니다.

Context Switching의 순간들

Context Switching은 인터럽트나 대기 상태에서만 발생하게 되지 않습니다. 타임 슬라이스 만료, 우선순위의 변경, 명시적인 호출등 다양한 상황에서도 발생될 수 있습니다. 모든 인터럽트는 Context Switching을 유발하지않고, 일부 인터럽트는 ISR에서 끝나고 Context Switching이 되지 않습니다.

제가 갖고 있던 처음의 생각이 틀렸다는 것을 알 수 있었습니다. Interrupt와 Wait 상태일때 Context Switching이 되는 것이 아닌, Interrupt는 Context Switching이 되지 않을 수 있다는 것입니다. 대신 Interrupt일때 타임 슬라이스가 끝났거나, 우선순위의 변경이 있다면 Interrupt일때도 Context Switching이 일어날 수도 있습니다.


정확한 내용

아래 내용은 작성한 글에서 기술적으로 정확한 부분입니다

Interrupt의 정의

Interrupt는 CPU가 현재 실행 중인 작업을 중단하고 외부 또는 내부 이벤트(예: 하드웨어 신호, 시스템 호출)를 처리하는 메커니즘입니다. CPU는 인터럽트를 감지하면 현재 상태를 저장하고, 인터럽트 벡터 테이블(IVT)을 참조해 해당 인터럽트 핸들러(ISR)를 실행합니다. 이 설명은 정확합니다.

Interrupt Vector Table (IVT)의 위치

  • IVT가 커널이 아닌 메모리의 특정 위치에 저장된다는 설명은 정확합니다. 이는 CPU의 하드웨어적으로 정의된 메모리 맵 구조에서 관리됩니다. 커널은 이 영역을 직접 수정하거나 참조할 수 있지만, IVT 자체는 CPU의 관리 하에 있습니다.

Interrupt Stack의 개념

Interrupt Stack은 인터럽트 처리 중에 CPU 상태(프로그램 카운터, 레지스터 등)를 저장하여 원래의 작업으로 복귀할 수 있도록 합니다. 일부 시스템에서는 일반 스택과는 별도로 ISR 전용 스택을 구성하며, 이는 작업 스택과의 충돌을 방지하기 위함입니다.

ISR(Interrupt Service Routine)의 위치

ISR이 커널에 포함된다는 설명도 일반적으로 맞습니다. 특히 리눅스 같은 운영체제에서는 ISR이 커널 모듈이나 디바이스 드라이버의 일부로 구현됩니다.

Context Switching과 Interrupt의 관계

Interrupt Handling이 항상 Context Switching을 유발하지는 않는다는 점은 정확합니다. Context Switching은 현재 프로세스 상태를 저장하고 다른 프로세스로 전환하는 작업을 의미하며, 모든 인터럽트가 Context Switching을 요구하지는 않습니다.


애매한 내용

아래는 명확히 다듬거나 추가적인 설명이 필요한 부분입니다:

CPU 메모리 공간

"CPU 메모리 공간 내의 특정 위치"라는 표현은 다소 혼란을 줄 수 있습니다. 실제로 이는 물리적 메모리의 특정 영역을 CPU가 접근 가능하도록 하드웨어적으로 매핑한 것을 의미합니다. CPU 내부에 메모리가 있는 것처럼 해석될 수 있으므로, IVT는 메인 메모리(RAM)의 특정 영역에 존재하며 CPU가 이를 관리한다는 점을 명확히 해야 합니다.

Interrupt Stack의 구조

Interrupt Stack에 저장되는 데이터로 프로세서 플래그를 언급했지만, 이는 시스템 아키텍처에 따라 다릅니다. x86 아키텍처의 경우 EFLAGS 레지스터를 저장하며, ARM 아키텍처에서는 상태 레지스터(CPSR)가 저장됩니다. 사용하는 CPU 아키텍처에 따라 상세히 설명하는 것이 좋습니다.

ISR 실행

ISR이 실행되면 "커널이 이를 처리한다"는 설명은 모호할 수 있습니다. ISR 자체는 커널 모드에서 실행되지만, 실제로는 CPU가 해당 ISR을 직접 실행합니다. 커널이 주도적으로 ISR을 호출한다고 오해할 여지가 있으므로 수정이 필요합니다.


3. 틀린 내용

IVT와 커널의 관계

"IVT가 커널 내에 있을 것이라고 생각했다"는 부분은 잘못된 추측입니다. IVT는 CPU 하드웨어가 직접 관리하며, 운영체제가 IVT의 엔트리 값을 설정하거나 수정할 수 있습니다. 즉, IVT는 커널의 일부가 아니며, 커널이 IVT를 간접적으로 제어합니다.

Interrupt Stack과 프로세스 스택

Interrupt Stack이 항상 프로세스 스택과 별도로 존재한다고 설명했지만, 이는 운영체제와 시스템 설정에 따라 다릅니다. 예를 들어, 일부 단순한 임베디드 시스템에서는 별도의 Interrupt Stack 없이 프로세스 스택을 사용할 수도 있습니다.


4. 추가해야 할 내용

IVT의 구성

IVT는 인터럽트 번호와 해당 인터럽트 핸들러 주소 간의 매핑 테이블입니다. 시스템마다 다르지만, x86 아키텍처에서는 IVT가 메모리 주소 0x0000에서 시작하며, 각 엔트리는 4바이트로 구성됩니다:

  • 2바이트: 핸들러 주소의 오프셋
  • 2바이트: 핸들러 주소의 세그먼트

ISR의 효율성 요구

ISR은 짧고 간단해야 하며, 긴 작업은 Bottom Half(리눅스에서는 SoftIRQ, Tasklet 등)로 처리하는 것이 일반적입니다. 이를 통해 실시간 성능 저하를 방지합니다.

Interrupt와 Context Switching 비교

Interrupt가 Context Switching으로 이어지는 경우:

  1. 인터럽트 핸들링 중에 I/O 대기가 발생하거나,
  2. 타임 슬라이스 만료로 스케줄러가 호출될 경우.