Linux Kernel(4.14) Hacks

rousalome.egloos.com

포토로그 Kernel Crash




[라즈베리파이][리눅스커널] 인터럽트 소개(0) #CS [라즈베리파이][커널]인터럽트

인터럽트란
인터럽트란 단어가 여러분들은 생소하신가요? 낯설게 들리는 분도 있고 귀에 익은 분도 있을 겁니다. 평소 인터럽트를 뭐라고 하죠? 일상생활에서 인터럽트는 보통 갑자기 생긴 일이나 하던 일을 멈춘다는 의미입니다. 예를 들면 책을 읽다가 전화가 와서 읽던 책을 덮어 놓고 전화를 받는 상황입니다. 

임베디드 시스템 관점으로 인터럽트는 뭘 의미하죠? 우선 하드웨어 관점으로는 하드웨어 변화를 감지해서 외부 입력으로 전달되는 전기 신호로 볼 수 있습니다. 예를 들면 키보드를 손으로 입력하면 하드웨어적으로 키보드 하드웨어의 변화를 감지하고 신호를 유발합니다. 보통 하드웨어 개발자들은 종종 오실로스코프란 장비로 인터럽트가 제대로 올라오는지 측정합니다. 인터럽트 신호를 측정하면 아래와 같은 파형을 볼 수 있습니다. 참고로 인터럽트 신호는 아래 박스와 같이 인터럽트를 식별하는 구간에 일정하게 5V(Voltage) 유지하거나 0V에서 5V로 변화하는 두 가지 종류로 분류합니다.

인터럽트란 단어가 조금 덜 낯설지 않나요? 이제는 소프트웨어 관점으로 인터럽트를 어떻게 처리하는지 살펴봅시다. 인터럽트가 발생하면 프로세스는 하던 일을 멈추고 이미 정해진 코드를 실행해서 하드웨어 변화에 대해 처리하는 방식으로 동작합니다. 여기서 “이미 정해진 코드 흐름”은 인터럽트 서비스 루틴(Interrupt Service Routine)이라고 부르기도 합니다.

그럼 CPU(ARM) 관점으로 인터럽트는 어떻게 처리할까요? 인터럽트는 x86, ARM CPU별로 처리하는 방식이 다릅니다. 라즈베리파이가 ARM CPU를 탑재하므로 ARM 프로세서 기준으로 살펴봐야겠습니다. ARM 프로세서에서 인터럽트는 익셉션(Exception)의 한 종류로 처리하므로 우선 익셉션 대해서 알아야 합니다. 

ARM 프로세서는 외부 하드웨어 입력이나 오류에 대한 사건이 발생하면 익셉션 모드로 진입합니다. 좀 어려운 개념인데 순간 이동과 비슷한 개념으로 생각해도 좋습니다. 인터럽트나 소프트웨어적인 심각한 오류가 발생하면 ARM 프로세스가 특정 주소를 실행시켜 버립니다. 이럴 때 각 익센션의 종류에 따라 이미 정해진 주소의 코드를 실행합니다. 이미 정해진 주소 코드를 익셉션 벡터(Exception Vector)라 하며 ARM 프로세서는 인터럽트를 익셉션 벡터 중 하나의 모드로 처리합니다. 

인터럽트를 잘 알아야 하는 이유
커널이 인터럽트를 처리하는 코드 흐름과 동작을 왜 잘 알아야 할까요? 인터럽트는 시스템 전반에 큰 영향을 끼치기 때문입니다. 또한, 리눅스 커널 시스템 전반을 잘 이해하기 위해서도 커널이 인터럽트를 어떻게 처리하는지 잘 알고 있어야 합니다. 조금 더 구체적인 이유를 알아볼까요?
1. 대부분 리눅스 드라이버는 인터럽트를 통해 하드웨어 디바이스와 통신합니다. 그래서 디바이스 드라이버 코드를 처음 분석할 때 인터럽트를 처리 방식을 가장 먼저 확인합니다. 자연스럽게 디바이스 드라이버 코드를 빨리 이해할 수 있습니다.
2. 인터럽트가 발생했을 때 프로세스는 이미 정해진 동작을 수행합니다. 인터럽트 처리 과정을 잘 알게 되면 자연스럽게 프로세스가 스택 메모리 공간에서 어떻게 실행되는지 알게 됩니다. 
3. 아키텍처(x86, ARM)에 따라 인터럽트 벡터를 다르게 구현합니다. 인터럽트 벡터가 어떻게 동작하는지 잘 알면 자연히 ARM 아키텍처에 대해 더 많이 알게 됩니다.

무엇보다 리눅스 커널을 새로운 보드에 포팅하거나 시스템 전반을 설계하는 개발자는 커널이 인터럽트를 어떻게 처리하는지 잘 알아야 합니다. 커널 패닉이나 시스템이 느려지는 성능 문제가 인터럽트 동작과 연관된 경우가 많기 때문입니다.
 
리눅스 커널에서 인터럽트 처리 흐름
인터럽트가 발생했을 때 커널은 이를 어떻게 처리할까요? 이 동작은 크게 3단계로 나눌 수 있습니다.
1. 인터럽트가 발생하면 인터럽트 벡터가 실행되어 프로세스 정보를 저장하고 관련 커널 함수를 호출합니다.
2. 커널에서는 발생한 인터럽트에 대응하는 인터럽트 디스크립터를 읽고 인터럽트 핸들러를 호출합니다.
3. 인터럽트 핸들러에서 하드웨어를 직접 제어하고 유저 공간에 이 변화를 알립니다.

좀 더 이해를 돕기 위해 리눅스 커널을 쓰는 안드로이드 모바일 디바이스를 예로 들겠습니다. 사용자가 손으로 화면을 만지면 내부에서 어떤 동작을 할까요? 조금만 상상해보세요. 하드웨어적인 터치 모듈이 변화를 감지하고 인터럽트 신호를 유발합니다. 이때 인터럽트 벡터가 실행되고 커널은 터치 인터럽트에 해당하는 번호로 인터럽트 디스크립터를 읽어 옵니다. 

이후 이 인터럽트 디스크립터로 터치 디바이스 드라이버에서 등록한 인터럽트 핸들러를 호출합니다. 결국 터치 인터럽트 핸들러는 해당 터치 인터럽트에 대해 화면을 업데이트하거나 하드웨어 터치 디바이스에 인터럽트를 잘 받아서 처리했음을 알리는 것입니다.

잠깐 여기서 인터럽트 관련 용어를 잠깐 소개합니다.
인터럽트 디스크립터: struct irq_desc란 구조체로 커널이 관리하는 인터럽트 속성과 세부 동작을 포함합니다. 인터럽트 번호, 인터럽트 핸들러, 인터럽터 실행 횟수 정보가 여기에 있어요.
인터럽트 컨택스트: 인터럽트를 처리 중이란 뜻입니다.
인터럽트 벡터: 인터럽트가 발생하면 ARM이 실행 시키는 함수입니다. 어셈블리로 구현되어 있습니다.

#Reference 시스템 콜


Reference(워크큐)
워크큐(Workqueue) Overview




핑백

덧글

댓글 입력 영역