Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

16192
888
89789


[리눅스커널] Soft IRQ 소개 6장. 인터럽트 후반부 처리

6.5 Soft IRQ 소개

Soft IRQ는 리눅스 커널을 이루는 핵심 기능 중 하나입니다. Soft IRQ 서비스 형태로 커널의 타이머, 스케줄링은 물론 네트워크 시스템에서 사용합니다. Soft IRQ 은 인터럽트 후반부 기법으로 씁니다. 이번 절에서는 Soft IRQ를 인터럽트 후반부 처리 중심으로 살펴봅니다. Soft IRQ 전체 구조를 익힌 다음 Soft IRQ에서 프로세스, 타이머 혹은 네트워크 시스템을 어떻게 처리하는지 알아보는 것이 좋습니다.  

6.5.1 Soft IRQ는 왜 알아야 할까?

Soft IRQ에 대해 알아보기 전 먼저 Soft IRQ를 왜 알아야 하는지 생각해 봅시다.

1. 리눅스 커널 입문자를 벗어나 중급 수준 개발자가 되려면 Soft IRQ가 뭔지 알아야 합니다. 반응 속도에 민감한 네트워크 패킷 처리나 고속 그래픽 처리 및 스토리지(UFS) 드라이버들은 Soft IRQ 핸들러를 이용해서 구현됐기 때문입니다.

2. 우리는 인터럽트가 발생하면 일하던 프로세스를 멈추고 인터럽트 핸들러를 실행한다고 알고 있습니다. 그런데 Soft IRQ는 인터럽트 핸들러가 수행하면 일하던 프로세스로 돌아가지 않고 바로 Soft IRQ 실행을 시작합니다. Soft IRQ 에서 실행 속도가 늦으면 시스템 반응 속도가 늦어질 수 있습니다. 시스템 성능 문제가 생겼을 때 체크해야 할 점검 포인트 중 하나입니다. 그래서 시스템 전반을 책임지는 개발자는 Soft IRQ를 잘 알아야 합니다.

3. 커널 타이머를 제대로 이해하려면 Soft IRQ 구조를 알아야 합니다. 드라이버에서 요청한 로컬 타이머들은 타이머 인터럽트가 발생한 다음 Soft IRQ 서비스로 실행하기 때문입니다.

4. 태스크릿은 Soft IRQ 서비스 형태로 사용합니다. 태스크릿을 제대로 이해하려면 Soft IRQ를 알아야 합니다.

6.5.2 Soft IRQ 서비스란

Soft IRQ 를 실행한다는 것은 Soft IRQ 서비스 요청을 받아 이를 처리하는 과정입니다. Soft IRQ 전체 흐름을 이해하려면 먼저 Soft IRQ 서비스에 대해 알아야 합니다.

Soft IRQ 서비스 소개

우선 Soft IRQ 서비스란 용어를 알아봅시다. 리눅스 커널에서는 다음과 같이 10가지 Soft IRQ 서비스를 지원합니다. 
[include/linux/interrupt.h]
const char * const softirq_to_name[NR_SOFTIRQS] = {
"HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "IRQ_POLL",
"TASKLET", "SCHED", "HRTIMER", "RCU"
};

“HI” 부터 “RCU” 까지가 Soft IRQ 서비스 이름입니다.
Soft IRQ 서비스는 부팅할 때 open_softirq() 란 함수를 써서 등록합니다.

각 Soft IRQ 서비스 종류는 다음 테이블과 같습니다.
우선순위 Soft IRQ 서비스 설명
0 HI_SOFTIRQ 가장 우선 순위가 높으며 TASKLET_HI로 적용 
1 TIMER_SOFTIRQ 동적 타이머로 사용
2 NET_TX_SOFTIRQ 네트워크 패킷 송신용으로 사용
3 NET_RX_SOFTIRQ 네트워크 패킷 수신용 사용
4 BLOCK_SOFTIRQ 블록 디바이스에서 사용
5 IRQ_POLL_SOFTIRQ IRQ_POLL 연관 동작
6 TASKLET_SOFTIRQ 일반 태스크릿으로 사용
7 SCHED_SOFTIRQ 스케줄러에서 주로 사용
8 HRTIMER_SOFTIRQ 현재 사용 안하나 하위 호완성을 위해 남겨둠
9 RCU_SOFTIRQ RCU 처리용으로 사용

이어서 Soft IRQ 서비스 실행 흐름을 단계별로 소개합니다.

Soft IRQ 서비스 라이프 사이클

Soft IRQ 서비스의 실행 흐름은 크게 3 단계로 나눌 수 있습니다. 다음 그림을 Soft IRQ 서비스 라이프 사이클에 대해서 알아봅시다.

 
  [그림 6.9] Soft IRQ 서비스 단계 별 실행 흐름

부팅 과정에서는 Soft IRQ 서비스를 1번 등록하고 [2]과 [3] 단계는 매우 자주 반복 실행합니다.

[1] 단계: 부팅 과정 
부팅 과정에서 open_softirq() 함수를 호출해 Soft IRQ 서비스를 등록합니다.

[2] 단계: 인터럽트 처리 
인터럽트 핸들러(인터럽트 컨택스트)나 인터럽트 서브 함수에서 raise_softirq() 함수를 호출해 Soft IRQ 서비스를 요청합니다. raise_softirq() 함수 이름 그대로 "Soft IRQ를 올린다"라고 부르는 경우도 있습니다.

이번 Soft IRQ 절에서는 이 동작을 "Soft IRQ 서비스를 요청한다"고 명시합니다.

[3] 단계: Soft IRQ 컨택스트 
__do_softirq() 함수에서 이미 요청한 Soft IRQ 서비스를 실행합니다.

인터럽트 핸들링이 끝나고 Soft IRQ 서비스를 바로 실행하는 동작을 Soft IRQ 컨택스트라고 합니다.
 
Soft IRQ 서비스 핸들러

 Soft IRQ 서비스 핸들러는 Soft IRQ 서비스를 실행할 때 호출하는 함수입니다. 부팅 과정에서 open_softirq() 함수로 Soft IRQ 서비스를 등록할 때 softirq_vec이란 전역 변수에 등록합니다. 다음 softirq_vec 전역 변수는 Trace32로 라즈베리안에 등록된 Soft IRQ 서비스 핸들러 정보입니다. 
(static struct softirq_action [10]) [D:0x80C02080] softirq_vec = (
    [0] = ((void (*)()) [D:0x80C02080] action = 0x80122888 = tasklet_hi_action),
    [1] = ((void (*)()) [D:0x80C02084] action = 0x80181270 = run_timer_softirq),
    [2] = ((void (*)()) [D:0x80C02088] action = 0x80614684 = net_tx_action),
    [3] = ((void (*)()) [D:0x80C0208C] action = 0x80615AB0 = net_rx_action),
    [4] = ((void (*)()) [D:0x80C02090] action = 0x804279B0 = blk_done_softirq),
    [5] = ((void (*)()) [D:0x80C02094] action = 0x0 = ),
    [6] = ((void (*)()) [D:0x80C02098] action = 0x8012299C = tasklet_action),
    [7] = ((void (*)()) [D:0x80C0209C] action = 0x801588EC = run_rebalance_domains),
    [8] = ((void (*)()) [D:0x80C020A0] action = 0x0 = ),
    [9] = ((void (*)()) [D:0x80C020A4] action = 0x8017ABC4 = rcu_process_callbacks))

이 함수들은 __do_softirq() 함수에서 호출됩니다.

Soft IRQ 서비스를 요청할 때는 raise_softirq() 함수나 raise_softirq_irqoff() 함수를 호출해야 합니다. 이 때 요청할 Soft IRQ 서비스 아이디를 지정해야 합니다.

6.5.3 Soft IRQ 전체 흐름도 소개

Soft IRQ 서비스를 소개했으니 이어서 Soft IRQ 전체 구조를 살펴봅시다.
 
[그림 6.10]  Soft IRQ 전체 실행 흐름도

위 그림과 같이 Soft IRQ 전체 동작 4단계로 분류할 수 있습니다. 단계별로 세부 동작을  알아봅시다. 

[1] 단계
인터럽트가 발생하면 해당 인터럽트 핸들러에서 Soft IRQ 서비스를 요청합니다. 이를 위해 raise_softirq_irqoff() 함수를 호출해야 합니다. 이 동작은 인터럽트 핸들러에서 IRQ_WAKE_THREAD를 반환하는 것과 유사합니다. 

[2] 단계
인터럽트 서비스 루틴 동작이 끝나면 irq_exit() 함수를 호출합니다. 여기서 Soft IRQ 서비스 요청 여부를 점검하고 요청한 Soft IRQ 서비스가 있으면 __do_softirq() 함수를 호출해서 해당 Soft IRQ 서비스 핸들러를 실행합니다. 만약 Soft IRQ 서비스 요청이 없으면 irq_exit() 함수는 바로 종료합니다. 

[3] 단계
__do_softirq() 함수에서 Soft IRQ 서비스 핸들러를 호출하다가 2ms 이상 시간이 걸리거나 10번 이상 Soft IRQ 서비스 핸들러를 호출하면 다음 동작을 수행합니다.
 - wakeup_softirqd() 함수를 호출해서 ksoftirqd 프로세스를 깨움
 - __do_softirq() 함수 종료

__do_softirq() 함수 실행 시간에 제약을 건 이유는 __do_softirq() 함수를 호출하는 irq_exit() 함수가 프로세스가 일을 멈춘 상태에서 실행하기 때문입니다.

[4] 단계
ksoftirqd 프로세스가 깨어나 [3] 단계에서 마무리 못 한 Soft IRQ 서비스 핸들러를 실행합니다.

Soft IRQ가 인터럽트 후반부를 처리하는 흐름을 알아보니 IRQ Thread 구조보다 과정이 더 복잡합니다. IRQ Thread는 인터럽트 핸들러에서 못한 일을 프로세스 레벨에서 실행합니다. 그런데 Soft IRQ 서비스는 인터럽트 핸들러가 수행된 후 바로 일을 시작합니다. 그러니 Soft IRQ 서비스 핸들러는 빨리 실행해야 합니다.

다음 소절에서는 Soft IRQ를 다른 인터럽트 후반부 기법과 비교해 보겠습니다.

6.5.4 후반부 기법으로 Soft IRQ는 언제 쓸까? 

Soft IRQ는 IRQ 스레드 기법보다 더 복잡한 구조인데 IRQ 스레드에 비해 훨씬 반응 속도에 민감한 리눅스 커널 시스템에서 사용합니다. 10개 Soft IRQ 서비스를 인터럽트 핸들러에서 요청하면 프로세스 레벨에서 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 서비스 실행 횟수 확인



    핑백

    덧글

    댓글 입력 영역