안녕하세요.
조금 긴 인터럽트 장을 끝냈고, 이번 장은 인터럽트 후반부 처리에 대한 내용을 확인합니다.
이 장도 양이 많기 때문에, 보면서 테스트하는데 시간이 좀 걸릴 것으로 생각됩니다.
1. 인터럽트 후반 처리에 대해서
인터럽트 핸들러는 짧고 간결하게 코드가 실행돼야 하기 때문에, 급하게 처리하지 않아도 되는 일은 조금 후에 처리한다는 기법입니다.
인터럽트가 발생했을 때 빨리 실행할 코드(인터럽트 핸들러 및 인터럽트), 실시간으로 빨리 실행하지 않아도 되는 코드(인터럽트 후반부 기법)로 나눌 수 있습니다.
1) Top Half/Bottom Half 란?
전문용어가 나 올 수가 있어서 확인해 보면, 인터럽트가 발생한 후 빨리 처리해야 하는 일은 Top Half(인터럽트가 하는 일), 조금 있다가 처리해도 되는 일은 Bottom Half(프로세스 레벨에서 수행하는 방식)라고 생각하면 됩니다.
2) 인터럽트 후반부 처리 기법의 종류
(1) IRQ 스레드 (Threaded IRQ)
리눅스 커널 2.6.30 버전 이후 도입된 방식이며, 하드웨어 인터럽트 핸들러의 후반부 처리를 별도의 커널 스레드에서 실행합니다.
인터럽트 발생 시 상반부(Top Half)는 여전히 인터럽트 문맥에서 최소한의 작업(예: 하드웨어 레지스터 읽기/쓰기, 인터럽트 비활성화)을 수행하고, 실제 대부분의 처리(후반부)는 이 스레드에서 이루어집니다. 프로세스 문맥에서 실행되므로, 슬립이 가능합니다.
다른 커널 스레드와 마찬가지로 우선순위가 할당될 수 있으며, 일반적인 스케줄링의 대상이 됩니다.
request_threaded_irq() 함수를 사용하여 등록합니다.
(2) 소프트웨어 인터럽트 (Softirqs)
커널 내부에서 raise_softirq() 함수를 통해 소프트웨어 인터럽트를 발생시키고, do_softirq() 함수에 의해 처리됩니다. 주로 네트워킹, 타이머 등 중요하고 빈번한 작업에 사용됩니다.
인터럽트 문맥(interrupt context)에서 실행될 수 있으며, 슬립(sleep)이 불가능합니다. ksoftirqd 커널 스레드에 의해 처리될 수도 있습니다.
(3) 태스크릿 (Tasklets)
Softirq 위에 구축된 메커니즘으로, 동적으로 생성하고 해제할 수 있습니다.
tasklet_struct 구조체를 사용하여 태스크릿을 정의하고, tasklet_init(), tasklet_schedule(), tasklet_kill() 등의 함수로 제어합니다.
동일한 태스크릿은 동시에 여러 CPU에서 실행되지 않도록 보장됩니다(하지만 다른 태스크릿은 동시에 실행 가능). Softirq와 마찬가지로 인터럽트 문맥에서 실행되며, 슬립이 불가능합니다.
(4) 작업 큐 (Workqueues)
작업 큐는 인터럽트 문맥이 아닌 프로세스 문맥(process context)에서 실행됩니다. 따라서 슬립(sleep)이 가능하며, 커널의 일반적인 스케줄링 정책에 따라 실행됩니다.
work_struct 구조체를 사용하여 작업을 정의하고, INIT_WORK(), schedule_work(), flush_work() 등의 함수로 제어합니다.
kworker 커널 스레드에 의해 처리되며, 긴 시간 실행되거나, 슬립이 필요한 작업에 주로 사용됩니다.
3) 인터럽트 후반 처리 선택 기준
4가지 기법 중 어떤 방식을 인터럽트 후반부 처리를 적용해야 하는 가는 기법마다 장단점이 있기 때문에 상황에 따라 다릅니다. 특징을 보고 적용해야 합니다.
(1) Softirq : 가장 빠르고 즉각적인 응답이 필요한, 매우 짧은 시간 내에 완료되어야 하며 슬립이 불가능한 작업에 사용합니다. (네트워킹 패킷 처리 등)
(2) Tasklet : Softirq와 비슷하게 빠른 처리가 필요하지만, 동적으로 생성/해제하고 싶을 때 사용합니다. Softirq보다는 유연하지만 여전히 짧은 시간 내에 완료되어야 하며 슬립이 불가능한 작업에 적합합니다.
(3) Threaded IRQ : 하드웨어 인터럽트의 후반부 처리가 길거나 슬립이 필요한 경우에 사용합니다. 특히 락을 오래 잡는 등의 이유로 인터럽트 문맥에 오래 머무르는 것이 부담스러울 때 유용합니다. 드라이버 개발 시 권장되는 방식 중 하나입니다.
(4) Workqueue : 가장 유연하며, 인터럽트와 직접적인 관련이 없어도 일반적인 커널 스레드에서 처리되어야 할 복잡하고 시간이 오래 걸리며 슬립이 필요한 작업에 사용됩니다. (I/O 완료, 파일 시스템 처리 등)
2. IRQ 스레드 (Thread IRQ)
1) IRQ란
IRQ는 Interrupt Request의 약자로 하드웨어에서 발생한 인터럽트를 처리한다는 의미이며, 인터럽트가 발생한 후 인터럽트 핸들러까지 처리되는 흐름을 의미합니다.
2) IRQ 스레드란
인터럽트 핸들러에서는 바로 처리하지 않아도 되는 일을 수행하는 프로세스이며, 인터럽트 후반부 처리를 위한 인터럽트 처리 전용 프로세스입니다. irq_thread 혹은 threaded IRQ 방식이라고도 합니다.
3) IRQ 스레드 확인
라즈베리 파이에서 IRQ 스레드를 ps 명령어로 확인할 수 있습니다.
$ ps -ely
프로세스 목록을 확인할 수 있으며 PID가 81번을 보면 오른쪽에 irq/35-brcmstb_과 바로 아래 irq/36-mmc1 도 확인할 수 있습니다.
커널 내부 함수에서 "irq/인터럽트 번호-인터럽트 이름"과 같은 규칙에 따라 IRQ 스레드 이름이 만들어집니다. 다음 글에서 확인할 예정입니다.
예를 들어, irq/36-mmc1 프로세스를 보자면 "mmc1이라는 이름의 36번 인터럽터를 처리하는 IRQ 스레드"라고 알 수 있습니다.
정리하자면, 인터럽트가 발생했을 때 바로 해야 하는 일은 인터럽트 핸들러에서 처리하고, 조금 후 프로세스 레벨에서 해도 되는 일은 IRQ 스레드에서 수행합니다.
감사합니다.
<참고 자료>
1. [도서] 디버깅을 통해 배우는 리눅스 커널의 구조와 원리 p375 ~ 389, wikibook
'IT > Linux Kernel' 카테고리의 다른 글
디버깅을 통해 배우는 리눅스 커널의 구조와 원리 1, 도서 공부하기 27 - IRQ 스레드 디버깅 실습 (11) | 2025.06.13 |
---|---|
디버깅을 통해 배우는 리눅스 커널의 구조와 원리 1, 도서 공부하기 26 - IRQ 스레드 생성 설명 (10) | 2025.06.10 |
디버깅을 통해 배우는 리눅스 커널의 구조와 원리 1, 도서 공부하기 24 - 인터럽트 디버깅 (7) | 2025.06.04 |
디버깅을 통해 배우는 리눅스 커널의 구조와 원리 1, 도서 공부하기 23 - 인터럽트는 비활성화할 시점 확인 (6) | 2025.05.30 |
디버깅을 통해 배우는 리눅스 커널의 구조와 원리 1, 도서 공부하기 22 - 인터럽트 핸들러 등록 과정 분석 (6) | 2025.05.28 |