인터럽트란 ?
하드웨어 관점에서 인터럽트란?
- 하드웨어의 변화를 감지해서 외부 입력으로 전달되는 전기 신호
손으로 키보드를 치면 하드웨어적으로 키도브 하드웨어의 변화를 감지하고 신호가 발생함

CPU 입장에서 인터럽트란?
- ARMv7, ARMv8 프로세서에서 인터럽트는
익셉션(Exception)의 한 종류로 처리됨
- 인터럽트를 처리하기 위한 특정 주소로 점프하게 되고,
- 해당 주소에서 인터럽트를 처리하기 위한 서비스 루틴이 진행된다.
디바이스별로 실행되는 인터럽트 핸들러

인터럽트가 발생한 후 이를 처리해야 할 코드를 2단계로 분류
- 인터럽트 핸들러에서 바로 실행해야할 부분
- 조금 후 실행해도 되는 코드
인터럽트 후반부 처리
인터럽트 핸들러에서 실행시간이 오래 걸리는 코드
- I/O를 시작하는 코드
- 과도한 while 반복문
- 유저 공간으로 uevent를 전달해서 인터럽트 발생을 알림
- 스케줄링을 지원하는 커널 함수 호출
인터럽트 후반부 기법들의 특징
| 처리 기법 | 특징 |
|---|
| IRQ 스레드(thread IRQ) | 인터럽트를 처리하는 전용 IRQ 스레드에서 인터럽트 후속 처리를 수행한다. 만약 rasp라는 24번 인터럽트가 있으면 irq/24-rasp란 IRQ스레드가 24번 인터럽트 후반부를 전담해 처리한다. |
| Soft IRQ | 인터럽트 핸들러 실행이 끝나면 바로 일을 시작한다. 인터럽트 핸들러에서 바로 처리해야 할 일을 마무리한 후 인터럽트 후반부 처리를 Soft IRQ 컨텍스트에서 실행한다. Soft IRQ 서비스 핸들러의 실행 도중 시간이 오래 걸리면 ksoftirqd 프로세스를 깨우고 Soft IRQ 서비스를 종료한다. ksoftirqd라는 프로세스에서 나머지 인터럽트 후반부를 처리하는 구조이다. |
| 태스크릿 | Soft IRQ 서비스를 동적으로 쓸 수 있는 인터페이스이자 자료구조이다. |
| 워크큐 | 인터럽트 핸들러가 실행될 때 워크를 워크큐에 큐잉하고 프로세스 레벨의 워커 스레드에서 인터럽트 후반부를 처리하는 방식이다. |
워크큐 소개
워크큐란
- 인터럽트 후반부 기법으로 사용됐으나 전반적인 후반부 기법으로 사용되는 기법
- 실행 시각에 민감한 후반부를 처리하는 용도로 워크큐의 워크를 사용하는 것은 적합하지 않음
드라이버 레벨에서 워크는 쓰기 용이
- 워크는
work_struct 구조체 변수만 설정하고 워크를 실행할 코드에 queue_work()/schedule_work() 함수만 추가
- 워크큐를 쓰면 드라이버를 조금 더 유연하게 설계할 수 있음
- 지연해서 후반부로 처리할 코드를 워크를 통해 처리
워크란?
- 워크(work)는 워크큐를 실행하는 기본 지연 단위
- 인터럽트 후반부 처리나 지연해야 할 작업을 워크에서 실행
워크의 실행 흐름
- 워크 큐잉
schedule_work
insert_work
- 워크 스레드 깨움
- 워크 스레드 실행
process_one_work
- 워크 핸들러 실행
워커 스레드란?
- 워커 스레드는 워크를 실행하고 워크큐 관련 자료구조를 업데이트하는 커널 스레드
- 워커 스레드의 세부 동작 방식은
worker_thread() 함수에 구현되어 있음
- 워커 스레드의 이름은
"kworker/"로 시작하며 워커풀의 종류에 따라 "kworker/"다음에 번호를 부여
라즈베리 파이에서 워커 스레드를 확인
ps -ely | grep worker
워크큐의 동작 방식
인터럽트 후반부 코드의 설계 원칙
- 인터럽트 핸들러로 빨리 처리해야 할 코드를 수행한 후 워크를 워크큐에 큐잉
- 인터럽트 후반부로 처리해야 할 코드를 워크 핸들러에서 처리
인터럽트 핸들러
- 인터럽트를 발생한 하드웨어에 인터럽트를 잘 받았다고 알림
- 인터럽트를 처리했다는 플래그 정보를 업데이트 함
- 워크를 큐잉
워크 핸들러
- 유저 공간에 인터럽트로 하드웨어가 변경된 사실을 알림
- 인터럽트를 처리했다는 사실을 디버깅 자료구조에 남김
인터럽트 후반부로 사용되는 워크큐의 실행 흐름

1단계
인터럽트 핸들러인 bcm2835_mbox_irq()함수에서 워크를 워크큐에 큐잉
2단계
워크를 큐잉하고 난 다음 wake_up_worker()함수를 호출해 워커 스레드를 깨움
3단계
워커 스레드가 깨어나면 스레드 핸들러인 worker_thread()함수가 일을 시작
화살표 방향으로 함수가 실행되며, process_one_work()함수에서 워크 핸들러인 bcm2835_mbox_work_callback 함수 호출