리눅스 - 인터럽트
인터럽트(Interrupt)
1. 개요
한국말로 직역하면 끼어듦, 가로막기이다. CPU가 프로세스를 실행 도중 즉각적인 처리가 필요한 일이 생길때 하드웨어 또는 소프트웨어에서 프로세서에 신호를 줘서 늦지 않게 이를 처리할 수 있도록 하는 것을 말한다.
종류에는 총 두 가지가 있다.
1) 하드웨어 인터럽트
키보드나 마우스와 같은 모든 하드웨어 입력이 하드웨어 인터럽트를 통해 작동한다. 기기 작동이 클럭과 동기화 되어있지 않으므로 클럭과 무관하게 발생하며 이러한 하드웨어 인터럽트를 통해 커널은 언제라도 방해받을 수 있다.
2) 소프트웨어 인터럽트
트랩이나 예외라고 불리기도 하는 이 소프트웨어 인터럽트는 운영체제나 시스템 서비스가 특정 기능을 수행하거나 오류 조건에 대응하도록 하는 역할을 한다.
클럭과 관계없이 발생하는 하드웨어 인터럽트와는 별개로 클럭과 동기화되어 발생하는데 이전 포스팅에서 언급했던 시스템 호출도 이러한 소프트웨어 인터럽트를 통해 발생한다.
인터럽트를 받은 프로세서는 인터럽트를 처리하기 위해 하던 일을 중단 한후 운영체제에 인터럽트가 발생했음을 알린다.
그러면 운영체제에서 상황에 맞게 인터럽트를 처리한다.
각 인터럽트별로 고유한 값을 할당 할 수 있으며 장비에 따라 다른 인터럽트를 할당 할 수 있다. 때문에 기기마다 발생하는 인터럽트는 다르며 기기마다 다르기때문에 운영체제는 인터럽트를 구별하고 인터럽트가 발생한 하드웨어가 어떤것인지 식별한다.
인터럽트 값을 인터럽트 요청(IRQ, Interrupt ReQuest) 라인이라고 부르며 각 IRQ라인에는 번호가 붙어있다.
일반 PC의 경우 IRQ0는 타이머 인터럽트, IRQ1은 키보드 인터럽트인 식으로 말이다. 하지만 모든 인터럽트 번호가 고정되어있지 않으며 PCI 버스에 연결된 장치는 동적으로 인터럽트 번호가 지정된다.
이렇게 식별된 인터럽트는 고유한 핸들러를 통해 처리되는데 이를 인터럽트 핸들러라고 한다.
2. 인터럽트 핸들러
인터럽트를 처리하이 위해 커널이 실행하는 함수를 인터럽트 핸들러(Interrupt Handler), 혹은 인터럽트 서비스 루틴(Interrupt Service Routine) 이라고 한다. 인터럽트를 발생시키는 각 장치별로 인터럽트 핸들러가 있으며 그 장치들이 인터럽트를 발생시키면 발생시킨 장치를 대상으로 하는 인터럽트 핸들러를 가지고 처리되는 식이다.
리눅스의 인터럽트 핸들러는 일반적인 C함수이며 표준적인 방식으로 커널이 핸들러에 정보를 전달할 수 있게 정해진 함수원형을 사용해야한다는 점만 제외하면 보통함수와 크게 다르지 않다.
단지 인터럽트가 발생했을때만 실행된다는 점과 인터럽트 컨텍스트(Interrupt Context)라고 불리는 특별한 컨텍스트에서 실행된다는 점이다. 이 인터럽트 컨텍스트에서 코드를 실행하고 있으며 실행이 중단 될수 없기 때문에 단위 컨텍스트(Atomic Context)라고도 불린다.
다른 프로세스를 중단하고 인터럽트 핸들러가 실행되기 때문에 중단된 프로세스를 최대한 빨리 재시작하기 위해서는 인터럽트 핸들러의 최대한 빠른 실행 속도를 요한다. 하지만 인터럽트가 연관된 작업 중에는 대량의 작업을 요하는 것도 있다. 네트워크 장치의 인터럽트 핸들러가 그 예시인데, 네트워크 패킷을 하드웨어에서 메모리로 복사하고 처리 작업을 수행한 다음에 좀 더 상위 계층이 패킷을 사용할 수 있게 데이터를 옮겨야야한다. 이런 경우 많은 시간이 걸릴 것이다. 따라서 리눅스에서는 전반부와 후반부로 나뉘어서 인터럽트가 처리 된다.
3. 인터럽트 처리 절차
1) 전반부
인터럽트 핸들러가 담당한다. 인터럽트 받은 즉시 실행되며 인터럽트 수신 확인이나 하드웨어 재설정처럼 처리시한이 중요한 작업만 처리한다. 그외 나중에 할 수 있는 일은 후반부 처리로 넘긴다.
2) 후반부
인터럽트 핸들러가 처리하지 않은 모든 인터럽트 관련 처리를 수행하는 것이다. 최대한 많은 일을 후반부 처리로 덜어낼 수록 시스템 제어권을 가능한한 빨리 돌려줄 수 있다. 이러한 작업들을 순차적으로 처리하기 위해 softirq, 태스크릿, 워크 큐가 있는데 여기에 작업을 넣어 순차적으로 처리한다.
a. softirq
컴파일시에 정적으로 할당되며 동적으로 등록하거나 제거될 수 없다. 시스템에서 가장 민감하고 중요한 후반부 처리를 수행할때 사용하도록 되어있다. 현재 이 softirq를 직접 사용하는 서브시스템은 네트워크와 블록 장치 둘 뿐이며 커널 타이머와 태스크릿도 sofirq를 기반으로 만들어져 있다.
b. 태스크릿(tasklet)
softirq 기반으로 만들어져있다. softirq과 유사하지만 인터페이스가 더 간단하고 락 사용제한이 더 유연하다. softirq가 실행횟수가 빈번하고 병렬처리가 필요할때만 사용한다면 태스크릿은 그외 광범한 대부분의 경우에 사용한다.
c. 워크 큐
지연 작업을 커널스레드 형태로 처리하는 방식으로 프로세스 컨텍스트에서 작업을 처리하는 방법이다.
따라서 통상적인 프로세스 컨텍스트의 이점을 모두 누릴 수 있으며 스케줄링이 가능하고 휴면상태로 전환될 수 있다.
※ 어떤 방식을 사용할 것인가?
이 셋 중에 어떤 후반부 방식을 이용할 것인지 결정하는 건 중요한 일이다.
softirq는 네트워크 서브시스템처럼 충분히 스레드화되어 깊숙한 부분까지도 프로세서별로 변수를 구분해 사용하고 있을 경우나 실행시간에 아주 민감하고 사용빈도가 높은 경우 사용할 수 있는 가장 빠른 대안이다. 하지만 최소한의 직렬화만 제공하므로 같은 유형의 softirq가 다른 프로세스에서 동시에 실행 될 수 있으므로 별도의 부가 처리를 해야한다.
태스크릿은 코드가 충분히 스레드화 되어있지 않을때 사용하기 좋은데 더 간단한 인터페이스를 가지고 있으며 별도의 처리 없이 같은 유형의 태스크릿이 동시에 실행되지 않으므로 구현 작업이 더 쉽다.
워크큐는 지연작업을 프로세스 컨텍스트에서 실행해야한다면 쓸 수 있는 유일한 방법이다. 휴면 상태로 돌리는 기능이 필요하지 않다면 태스크릿이나 softirq를 사용하는게 더 좋다. 커널 스레드를 사용하기 때문에 컨텍스트 전환이 필요하고, 이로 인해 부가 비용이 가장 크기 때문이다.
※ kernel 4.x부터 변경 사항
태스크릿이 softirq에 포함되었다. API 래퍼되어 사용은 할수 있다. 이는 호환성을 유지하기 위한 것으로 보인다. 또한 softirq가 프로세스 컨텍스트에서도 사용가능 할 수 있게 변경 되었다.
참고문헌
- 위키백과 - 인터럽트
- 리눅스 커널 심층분석 (에이콘 임베디드 시스템프로그래밍 시리즈 33, 로버트 러브 저자(글) · 황정동 번역)
- geeks for geeks - interrupt
- 문c 블로그 - Interrupts -4- (top-half & bottom-half)