인터럽트와 쓰레드

인터럽트와 쓰레드는 유사하지만 둘 사이에는 약간의 차이가 있습니다.
PC급 하드웨어의 범용 운영 체제에서 실행되는 프로그램의 경우 쓰레드는 동시 프로그래밍을 지원하는 가장 중요한 개념일 수 있지만, 
반대로 소형 마이크로 컨트롤러 장치를 기반으로 하는 임베디드 시스템에서 동시성을 표현하는데 가장 중요한 방법은 인터럽트입니다.
또한, 인터럽트 구동 시스템에서는 경쟁 조건이 없는지 확인하는 것이 중요합니다. 


차단 (Blocking)

인터럽트는 Blocking할 수 없고, 다른 인터럽트에 의해 선점되지 않는 한 완료될 때까지 실행됩니다. 
Blocking이 불가능한 것은 매우 불편하고, 복잡한 Logic이 인터럽트 코드로 구현되어서는 안되는 주된 이유 중 하나입니다.

 

반대로, Non-blocking 실행에는 몇 가지의 장점이 있습니다. 

아래에서 컨텍스트란 "핸들링하기 위한 접근 수단" 이라고 생각하시면 됩니다.

 

첫째, 비 인터럽트 실행 컨텍스트 외에 모든 인터럽트는 단일 호출 스택을 공유 할 수 있습니다. 

쓰레드는 자체 스택을 필요로하므로 일반적으로 RAM이 KB인 로우 엔드 MCU에 적합하지 않습니다.  

 

둘째, 인터럽트는 절대로 차단되지 않기 때문에 내부 상태는 비 인터럽트 코드에 보이지 않습니다. 

다시 말해, 인터럽트는 비 인터럽트 컨텍스트에서 실행되는 코드와 관련하여 원자적으로 실행됩니다. 

 

셋째, Non-blocking 실행은 인터럽트에 대부분의 교착 상태 (Deadlock)가 적용되지 않음을 의미합니다.

 

선점 및 일정 (Preemption and scheduling)

쓰레드는 일반적으로 대칭적 선점 관계를 갖습니다. 
특정 쓰레드 쌍에 대해 둘 중 하나가 다른 선점을 선점 할 수 있고, 반대로 비대칭 선점 관계는 인터럽트의 표준입니다.


첫째, 모든 인터럽트는 비 인터럽트 코드를 선점 할 수있는 반면, 비 인터럽트 코드는 어떤 인터럽트도 선점 할 수 없습니다. 
둘째, 인터럽트는 고정된 우선 순위를 사용하여 스케줄되며, 인터럽트 핸들러 간 비대칭적인 선점 관계가 발생합니다 .


PC의 프로그래밍 가능한 인터럽트 컨트롤러와 같은 일부 하드웨어 플랫폼은 인터럽트 우선 순위 스케줄링을 시행합니다. 
다른 시스템에서는 우선 순위가 지정된 인터럽트 예약을 소프트웨어로 구현해야합니다. 

예를 들어, Mica2 센서 네트워크 노드의 기반이되는 인기있는 MCU 인 Atmel ATmega128은 동시에 보류중인 인터럽트 중

우선 순위 예약을 수행합니다. ATmega128에서 인터럽트가 실행되기 시작하면 선점 할 수 있습니다. 

인터럽트가 활성화 된 경우 우선 순위의 인터럽트에 의해 이 플랫폼에서 우선 순위 기반 선점 예약을 구현하려면

소프트웨어가 다양한 인터럽트와 관련된 개별 활성화 비트를 조작해야합니다.


동시성 제어 (Concurrency control)

쓰레드 Lock은 Blocking을 사용, Lock된 Resource가 사용 가능해질 때까지 쓰레드가 지정된 프로그램 포인트를 통과하지 못하도록 합니다.
인터럽트는 일단 실행이 시작되면 차단될 수 없으므로, 동시성 제어는 인터럽트가 처음부터 실행되는 것을 방지하는 것으로 구성됩니다. 
이는 모든 인터럽트를 비활성화하거나 특정 계산을 방해할 수 있는 인터럽트만 선택적으로 비활성화하여 수행됩니다. 
 
인터럽트 기반 시스템의 선점은 비대칭적이므로 잠금이 되어야합니다. 
다시 말해, 인터럽트와 관련하여 원자적으로 실행하기 위해 비 인터럽트 컨텍스트가 인터럽트를 비활성화 해야하는 반면, 
인터럽트 모드에서 실행되는 코드는 인터럽트되지 않은 코드와 관련하여 실행하기 위해 특별한 조치를 취할 필요가 없습니다.

 

재진입 (Reentrance)

인터럽트가 다시 발생하면 동일한 핸들러가 여러 번 동시에 호출 될 수 있습니다.
재진입 인터럽트는 accidental 및 deliberate 두 가지 유형으로 제공됩니다. 

accidental 재진입은 개발자가 인터럽트 처리기 내부에서 인터럽트를 활성화한 결과를 잘못 판단할 경우 발생합니다. 
이 유형의 재진입은 일반적으로 버그가 있는 시스템으로 이어지고, 

실제 임베디드 시스템에서는 일반적이기 때문에 재진입 유형에 대해 언급합니다. 

deliberate 재진입은 인터럽트 대기 시간을 줄이는 데 사용할 수있는 정교한 기술입니다. 

시간 제약이 있는 장기 실행 인터럽트 핸들의 시작 부분을 코드로 닫을 때 유용합니다. 
이전 호출자가 실행을 완료하기 전에 처리기의 후속 호출이 실행되도록 허용하여 처리기 초기 부분의 평균 대기 시간을 줄일 수 있습니다.

재진입에는 피할 수없는 두 가지 문제점이 있습니다. 
첫째, 처리기의 이후 부분은 평균 대기 시간이 줄어들지 않고 증가합니다. 
둘째, 실제로 정확한 재진입 인터럽트 코드를 생성하는 것은 어렵습니다.


호출 스타일 (Invocation style) 

일부 인터럽트는 자연스럽게 호출되고, 네트워크 인터페이스에 의해 생성 된 인터럽트를 예로 들 수 있습니다.
반면에 나머지 인터럽트들은 실행중인 프로그램이 수행한 작업에 대한 응답으로만 발생합니다. 

예를 들어, 아날로그-디지털 변환기 (ADC) 완료 인터럽트와 마찬가지로 타이머 인터럽트가 요청됩니다. 
인터럽트 요청과 후속 인터럽트 간의 관계는 하드웨어의 의미를 이해해야 볼 수 있습니다.

 

인터럽트 연기 (Deferring interrupts)

인터럽트에는 때로 시간 제약이 있고, 인터럽트들은 대기 후 제한된 시간 내에 명령을 실행해야 합니다. 
이러한 제약 조건에서 프로그램을 구현하는 좋은 방법은 인터럽트 처리기를 짧게 만드는 것입니다. 

일반적으로 인터럽트가 하드웨어 조건을 인지하고 인터럽트와 관련된 데이터를 메모리 버퍼로 이동시키는 것과 같이 

인터럽트 요청과 관련된 최소 계산을 수행하는 것입니다. 
이후, 인터럽트 처리기는 하단 처리기 또는 쓰레드와 같은 지연된 컨텍스트에서 더 오래 실행되는 계산을 시작합니다.

'Etc' 카테고리의 다른 글

PNG / GIF / JPEG / BMP 확장자 비교  (0) 2020.12.22