리눅스 커널에서의 인터럽트 처리 흐름
인터럽트가 발생했을 때 커널이 이를 처리하는 과정은 다음과 같이 3단계로 나눌 수 있습니다.



 1 단계: 인터럽트 발생
인터럽트가 발생하면 프로세스 실행을 중지하고 인터럽트 벡터로 이동합니다. 인터럽트 벡터에서 인터럽트 처리를 마무리한 후 다시 프로세스를 실행하기 위해 실행 중인 프로세스 레지스터 세트를 스택에 저장합니다. 이후 커널 내부 인터럽트 함수를 호출합니다. 


 2단계: 인터럽트 핸들러 호출
커널 내부에서는 발생한 인터럽트에 대응하는 인터럽트 디스크립터를 읽어서 인터럽트 핸들러를 호출합니다. 


 3단계: 인터럽트 핸들러 실행
인터럽트 핸들러에서 하드웨어를 직접 제어하고 유저 공간에 이 변화를 알립니다.

 


이해를 돕기 위해 한 가지 예를 들어보겠습니다. 안드로이드 휴대폰에서 화면을 손을 만지는 동작에서 여러분이 손으로 휴대폰 화면을 터치하면 내부 동작은 다음과 같은 단계로 나눌 수 있습니다.

 1단계: 터치 인터럽트 발생
하드웨어적인 터치 모듈이 변화를 감지하고 터치 모듈에 대한 인터럽트를 발생시킵니다. 이때 인터럽트 벡터가 실행됩니다.


 2단계: 터치 인터럽트 핸들러 호출
커널은 터치 인터럽트 번호로 해당 인터럽트 디스크립터를 읽습니다. 다음 인터럽트 디스크립터에 저장된 인터럽트 핸들러 주소를 찾아 인터럽트 핸들러를 호출합니다.


 3단계: 터치 인터럽트 핸들러 실행
결국 터치 인터럽트 핸들러는 해당 터치 인터럽트를 받아 정해진 처리를 합니다. 화면을 업데이트하거나 하드웨어 터치 디바이스에 인터럽트를 잘 받았다는 사실을 알립니다. 


“인터럽트 디스크립터”, “인터럽트 벡터” 같은 낯선 용어로 설명했는데, 이러한 용어의 공학적 의미는 하나하나 각 장에서 다룰 예정입니다. 


인터럽트가 발생하면 이를 커널이 처리하는 과정을 터치 드라이버를 예로 들어 살펴봤습니다. 인터럽트 발생을 처리하는 단계를 함수 흐름과 실행 주체별로 분류하면 다음 그림과 같습니다. 

 


그림 5.5 ARM 프로세서/리눅스 커널/디바이스 드라이버별 인터럽트 처리 흐름

전체 실행 흐름은 다음의 3단계로 분류할 수 있습니다.

1. ARM 프로세스
인터럽트가 발생하면 실행 중인 코드를 멈춘 후 인터럽트 벡터로 실행 흐름을 이동합니다. ARM 프로세스와 연관된 동작입니다. 

2. 리눅스 커널
인터럽트 벡터로 프로그램 카운터를 브랜치합니다. 커널 인터럽트 내부 함수에서 인터럽트를 관리하는 자료구조인 인터럽트 디스크립터를 읽습니다. 인터럽트 디스크립터에 저장된 인터럽트 핸들러를 호출합니다.

3. 디바이스 드라이버
각 디바이스 드라이버에서 등록한 인터럽트 핸들러를 실행해 인터럽트 발생에 대한 처리를 수행합니다.

정리하면 “인터럽트로 하드웨어적인 변화가 발생하면 리눅스 커널에서 어떻게 처리하는가"입니다. 이를 위해 이번 절에서는 인터럽트에 대해 소개했으니 이어지는 절에서 인터럽트 컨텍스트에 대해 살펴보겠습니다.

+ Recent posts