안녕하세요.
Soft IRQ를 이어서 언제 요청하는지 대해서 좀 더 확인해보려고 합니다.
1. Soft IRQ 서비스 요청의 전체 흐름
전체 흐름을 보면서 Soft IRQ 서비스 요청하는 시점을 알아보겠습니다. 아래 그림은 Soft IRQ 서비스 요청 시의 자료구조입니다.
인터럽트 핸들러나 인터럽트 핸들러 서브루틴에서 호출하는 함수의 동작의미 합니다.
__raise_softirq_irqoff는 Soft IRQ 서비스를 요청하는 동작을 하며, or_softirq_pending 함수로 irq_stat[cpu].__softirq_pending에 Soft IRQ 서비스 비트를 활성화하는 역할을 합니다.
irq_stat는 배열이 percpu 타입의 변수로 CPU 코어의 개수만큼 존재합니다.
2. raise_softirq 함수 확인
linux# vim kernel/time/timer.c
TIMER_SOFTIRQ 서비스를 요청한다면, raise_softirq(TIMER_SOFTIRQ) 열거형으로 정의된 정수형 1이 전달됩니다.
linux# vim kernel/time/softirq.c
raise_softirq() 함수를 호출하기 위해서는 정수형 인자가 필요하다는 것을 알 수 있습니다.
함수의 내용은 자신에게 전달된 인자를 전달하면서 raise_softirq_irqoff() 함수를 호출합니다.
그리고 위아래 local_irq_save(), local_irq_restore() 함수는 CPU 라인의 인터럽트를 비활성화합니다. 이는 Soft IRQ 서비스를 요청하는 중에 인터럽트가 다시 발생하는 상황을 막기 위해서입니다.
이어서, raise_softirq_irqoff() 함수를 보면,
__raise_softirq_irqoff() 함수를 호출하고 현재 실행코드가 인터럽트 컨텍스트인지 점검합니다. 인터럽트 컨텍스트가 아니면 wakeup_softirqd() 함수를 호출해 ksoftirqd 스레드를 깨웁니다.
이것으로 인터럽트 컨텍스트가 아닐 때도 Soft IRQ 서비스 요청을 할 수 있다는 것입니다.
__raise_softirq_irqoff()를 따라가 보면 ftrace 로그를 출력할 수 있는 함수와 입력 인자인 nr을 왼쪽으로 비트 시프트 연산한 결괏값을 or_softirq_pending() 함수에 전달합니다.
3. irq_stat 변수 확인
or_softirq_pending() 함수를 분석해서 irq_stat[cpu].__softirq_pending 변수가 변경되는 확인 해보겠습니다.
or_softirq_pending() 함수는 (__this_cpu_or(local_softirq_pending_ref, (x))) 매크로로 치환됩니다.
__this_cpu_or() 함수 첫 번째 인자로 지정한 percpu 타입 변수와 두 번째 인자에 대해 |= 연산을 합니다.
즉, or_softirq_pending() 함수를 호출하면 percpu 타입의 irq_stat 변수에 인자와 OR 연산한 결과를 더합니다.
irq_stat[cpu].__softirq_pending |= x;
예로,
CPU 번호 | 10진수 | 2진수 | 비트 연산자 | Soft IRQ 서비스의 아이디 |
3 | 6 | 110 | (1<<2)|(1<<1) | NET_TX_SOFTIRQ | TIMER_SOFTIRQ |
4. Soft IRQ 서비스를 요청을 확인 방법
커널은 Soft IRQ 서비스 요청 여부를 알려주는 local_softirq_pending() 함수를 제공합니다. true면 Soft IRQ 서비스를 요청했다고 판단할 수 있습니다.
local_softirq_pending() 함수를 커널 어느 코드에서 호출하는지 확인할 수 있습니다. Soft IRQ 서비스 요청 여부는 두 군데서 확인합니다.
- 인터럽트 핸들러 처리를 마무리한 호출 하는 irq_exit() 함수
- ksoftirqd 스레드핸들러 함수인 run_ksoftirqd() 함수
linux# vim kernel/softirq.c
411번 줄에 보면,
현재 실행 중인 코드가 인터럽트 컨텍스트 상태인지와 Soft IRQ 서비스 요청이 있는지 조건을 확인 후 Soft IRQ 서비스를 실행할지 결정합니다.
640번 줄에 run_ksofirqd() 함수에서 보면 local_softirq_neding() 함수를 호출해서 Soft IRQ 서비스 요청이 있었는지 점검합니다.
이렇게 Soft IRQ 서비스가 언제 요청하는지 확인해 보았습니다.
감사합니다.
<참고 자료>
1. [도서] 디버깅을 통해 배우는 리눅스 커널의 구조와 원리 p461 ~ 472, wikibook
'IT > Linux Kernel' 카테고리의 다른 글
디버깅을 통해 배우는 리눅스 커널의 구조와 원리 1, 도서 공부하기 31 - ksoftirqd 스레드에 대해서 (5) | 2025.06.27 |
---|---|
디버깅을 통해 배우는 리눅스 커널의 구조와 원리 1, 도서 공부하기 30 - Soft IRQ 처리 시점 확인 (2) | 2025.06.24 |
디버깅을 통해 배우는 리눅스 커널의 구조와 원리 1, 도서 공부하기 28 - Soft IRQ 서비스 확인 (3) | 2025.06.17 |
디버깅을 통해 배우는 리눅스 커널의 구조와 원리 1, 도서 공부하기 27 - IRQ 스레드 디버깅 실습 (11) | 2025.06.13 |
디버깅을 통해 배우는 리눅스 커널의 구조와 원리 1, 도서 공부하기 26 - IRQ 스레드 생성 설명 (10) | 2025.06.10 |