Soft IRQs is the term used for the low-level mechanism that implements deferring work from interrupt handlers but that still runs in interrupt context. - linux kernel labs
Soft IRQ
란 인터럽트 핸들러에서 지연된 작업(deferring work) 을 처리하는 저수준 기법이다. 그러나 이는 여전히 interrupt context
에서 수행된다. (이전에 본 threaded IRQ
는 irq_thread
라고 하는 kernel thread
에서 수행된다. 당연히 이는 프로세스 컨텍스트이다.)
여기에서 중요한 것은 Soft IRQ
는 인터럽트 핸들러(전반부)가 끝난 뒤에 인터럽트 컨텍스트에서 바로 실행된다. 다른 말로 하자면, 즉각적으로 실행되야 하는 것뿐만 아니라 빨리 실행을 끝 마쳐야 한다는 것이다. 왜 Why? Soft IRQ
가 길어지면 결국 선점당한 작업이 지연되기 때문이다.
Soft IRQ
등록 Soft IRQ
는 open_softirq()
함수를 통해 가능하며 6.16 커널 기준으로 10개의 카테고리를 제공한다:
이 값을 open_softirq()
함수의 인자로 전달해 해당하는 카테고리의 핸들러를 등록할 수 있다. 위의 주석을 읽어보면 알겠지만 Soft IRQ
는 커널 내에서 사용하는 후반부로 이미 다 구현이 되어 있고 이는 부팅 시점에 등록이 된다.
Soft IRQ
요청 Soft IRQ
의 실행은 보통 인터럽트 핸들러에서 요청하게 된다. 뭐, 당연한 얘기이다. 애초에 후반부가 존재하는 이유가 전반부에서 미처 끝내지 못한 작업이 있기 때문이다. 전반부(인터럽트 핸들러)에서 Soft IRQ
를 요청하는 함수는 __raise_softirq_irqoff()
함수이다:
언더 스코어가 붙지 않은 raise_softirq()
함수도 있는데 이는 local_irq_disable()
과 local_irq_enable()
가 추가된 버전이다. 대부분의 경우, __raise_softirq_irqoff()
함수를 호출하게 된다.
그런데 이것도 너무나 당연한 얘기이다. 왜냐하면 Soft IRQ
를 요청하는 시점은 앞서 말한 것처럼 전반부(bottom-half)
이다. interrupt handler
를 실행하는 시점에서 IRQ
를 enable
/disable
할 일이 과연 있을까? 애초에 interrupt handler
에 들어온 시점에서 IRQ
는 disable
되어 있다.
프로세서의 인터럽트가 비활성화되어 있지 않으면, 프로세서는 하던 일을 중단하고, 인터럽트 시스템을 비활성화시킨 다음 미리 정해진 위치의 메모리에 있는 코드를 실행한다. - LKD 208pg.
Soft IRQ
실행 가장 먼저 인터럽트가 들어오면(__common_interrupt()
) 인터럽트 핸들러(rio_interrupt()
)가 실행이 되고, 필요에 따라 Soft IRQ
를 요청(__raise_softirq_irqoff()
) 하게 된다.
인터럽트 핸들러가 끝나면 irq_exit_rcu()
함수가 호출되고 여기에서 handle_softirqs()
함수가 실행된다. 최종적으로 등록된 Soft IRQ
핸들러(net_tx_action()
)가 실행된다.
ksoftirqd
전술했듯이 Soft IRQ
는 빠르게 실행되어야 한다. 그러나 Soft IRQ
의 처리 작업이 많아 빠르게 실행되지 못 할 수도 있다. 그래서 커널은 지연된 Soft IRQ
작업을 ksoftirqd
에서 처리하도록 했다. ksoftirqd
는 커널이 부팅될 때에 생성되는 커널 스레드로 Soft IRQ
에서 처리하지 못한 남은 작업을 이어서 하도록 했다.
그러나 재미있는 점은 실행은 커널 스레드에서 되지만 ksoftirqd
가 실행될 때에는 local_irq_disable()
을 호출해 인터럽트를 제한했다는 점이다. 이 말은 결국 ksoftirqd
또한 interrupt context 에서 실행되는 것과 크게 다를 바 없음을 뜻한다. 또한 ksoftirqd
는 절대 인터럽트에 의해 선점되지 않으므로 Soft IRQ
가 재실행되지 않는다.