Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

15192
888
89788


[리눅스커널] Soft IRQ 서비스에 대해서 6장. 인터럽트 후반부 처리

6.6 Soft IRQ 서비스

이번 절에서는 Soft IRQ 서비스의 의미와 서비스 등록 과정에 대해 살펴봅니다. 

6.6.1 Soft IRQ 서비스 알아보기 

Soft IRQ를 설명하면서 낯선 용어를 설명했는데, 이제부터 그 의미를 하나하나씩 살펴 보겠습니다. Soft IRQ 서비스란 용어를 소개합니다.

Soft IRQ 서비스를 빨리 이해하려면 코드를 먼저 봐야 합니다. Soft IRQ 서비스는 아래 enum으로 정의한 코드와 같습니다.
[https://elixir.bootlin.com/linux/v4.19.30/source/include/linux/interrupt.h]
enum
{
HI_SOFTIRQ=0,
TIMER_SOFTIRQ,
NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ,
BLOCK_SOFTIRQ,
IRQ_POLL_SOFTIRQ,
TASKLET_SOFTIRQ,
SCHED_SOFTIRQ,
HRTIMER_SOFTIRQ, 
RCU_SOFTIRQ,  
NR_SOFTIRQS
};

const char * const softirq_to_name[NR_SOFTIRQS] = {
"HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "IRQ_POLL",
"TASKLET", "SCHED", "HRTIMER", "RCU"
};

리눅스 커널에서는 Soft IRQ 서비스 종류를 지정해 놨습니다. 위 코드를 보면 10개나 됩니다. enum 타입으로 정의된 이름으로 타이머, 네트워크 그리고 블록 디바이스별로 Soft IRQ 서비스가 있습니다.

Soft IRQ 서비스는 어떻게 실행할까요? 각 Soft IRQ 서비스별로 등록된 서비스 핸들러 함수가 실행할 때 Soft IRQ 서비스를 실행합니다. Soft IRQ 서비스 핸들러는 어디서 확인할 수 있을까요? softirq_vec 변수가 Soft IRQ 서비스 핸들러 정보를 저장합니다.

다음에 라즈비안에서 Soft IRQ 서비스는 어떤 코드에서 등록하는지 알아봅시다.

6.6.2 Soft IRQ 서비스 핸들러는 언제 등록할까?

Soft IRQ 서비스 핸들러 등록과 Soft IRQ 서비스 등록은 같은 의미입니다. 왜냐면 Soft IRQ 서비스 등록을 할 때 Soft IRQ 핸들러 함수를 등록해야 하기 때문입니다.

Soft IRQ 서비스 핸들러를 등록하려면 다음 규칙에 따라 open_softirq() 함수를 호출해야 합니다. 
open_softirq(Soft IRQ 서비스 아이디, Soft IRQ 서비스 핸들러);

우선 TIMER_SOFTIRQ이란 Soft IRQ 서비스 아이디로 Soft IRQ 서비스 핸들러를 등록하는 코드를 살펴 보겠습니다.
[https://elixir.bootlin.com/linux/v4.19.30/source/kernel/time/timer.c]
1 void __init init_timers(void)
2 {
3 init_timer_cpus();
4 open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
5 }

위 코드를 보면 init_timer() 함수에서 open_softirq() 함수를 호출합니다. 첫 번째 인자는 Soft IRQ 서비스 아이디, 두 번째로 run_timer_softirq() 함수를 지정합니다. 

참고로, init_timers() 함수 선언부를 보면 __init 매크로가 붙어 있으니 부팅 도중 한번 실행됩니다.

open_softirq() 함수 코드를 보면 예상한 대로 Soft IRQ 서비스 핸들러 정보를 저장하는 softirq_vec에 함수 주소를 지정합니다.
[https://elixir.bootlin.com/linux/v4.19.30/source/kernel/softirq.c]
void open_softirq(int nr, void (*action)(struct softirq_action *))
{
softirq_vec[nr].action = action;
}

커널에서는 softirq_vec 전역 변수는 Soft IRQ 벡터라고 부릅니다. 이 전역 변수는 Soft IRQ 서비스 핸들러 함수 포인터를 저장합니다. softirq_vec은 NR_SOFTIRQS 크기만큼 배열입니다. 
[https://elixir.bootlin.com/linux/v4.19.30/source/kernel/softirq.c]
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;

이렇게 각 Soft IRQ 서비스 아이디 별로 Soft IRQ 서비스를 등록하면 softirq_vec[nr].action 필드에 Soft IRQ 서비스 핸들러 함수를 볼 수 있습니다.

조금 후 살펴볼 예정이지만, Soft IRQ 서비스 핸들러는 다음 코드와 같이 __do_softirq() 함수에서 호출합니다. TIMER_SOFTIRQ Soft IRQ 서비스 아이디인 경우 __do_softirq() 함수에서 run_timer_softirq() 함수를 호출합니다.
[https://elixir.bootlin.com/linux/v4.19.30/source/kernel/softirq.c]
1 asmlinkage __visible void __softirq_entry __do_softirq(void) {
2 struct softirq_action *h;
3 h = softirq_vec;
4 h->action(h);

위 코드는 __do_softirq() 함수에서 Soft IRQ 벡터인 softirq_vec 변수를 읽어서 Soft IRQ 핸들러 함수를 호출하는 부분만 가져온 것입니다. 위 4번째 줄 코드에서 Soft IRQ 핸들러 함수를 호출합니다.

여기까지 Soft IRQ 서비스를 등록 과정을 살펴봤습니다. 세부 코드는 간단합니다. Soft IRQ 서비스 아이디와 Soft IRQ 서비스 핸들러를 지정해서 open_softirq() 함수를 호출하는 것입니다.

라즈비안에서는 Soft IRQ 서비스를 어떻게 등록하는지 알아볼까요? 코드만 봐서 Soft IRQ 서비스 전체 개수를 파악하기는 어렵습니다. 직접 라즈베리파이에서 Soft IRQ 서비스를 어떻게 등록하는지 알아 보겠습니다.

"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"


# Reference 인터럽트 후반부 처리








6.9 Soft IRQ 서비스는 누가 언제 처리하나?




6.13 Soft IRQ 디버깅
6.13.1 ftrace Soft IRQ 이벤트 분석 방법
6.13.2 /proc/softirqs로 Soft IRQ 서비스 실행 횟수 확인



핑백

덧글

댓글 입력 영역