Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

6363
1898
209235


[리눅스커널][태스크릿] 태스크릿(struct tasklet_struct) 이란 무엇인가 6. 인터럽트 후반부 처리

태스크릿은 프로세스와 전혀 상관 없는 용어입니다. 태스크릿이란 이름 때문에 많은 분이 프로세스와 관련됐다고 오해할 수 있습니다.

태스크릿은 Soft IRQ 서비스 중 하나로 동적으로 Soft IRQ 서비스를 쓸 수 있는 인터페이스입니다. 드라이버 레벨에서 태스크릿은 자주 쓰고 활용합니다.

태스크릿은 무엇일까?

우리는 인터럽트 후반부 기법으로 Soft IRQ에 대해 다음과 같은 내용을 배웠습니다.  
인터럽트 핸들링 후 바로 Soft IRQ 서비스 실행 
인터럽트 발생 후 바로 후반부를 처리할 때 용이 

다른 인터럽트 후반부 기법에 비해 Soft IRQ는 인터럽트 후반부를 빨리 처리해야 할 때 적용합니다.

그러면 이런 장점이 있는 Soft IRQ 서비스를 드라이버 레벨에서 쓰면 좋을 때가 있습니다.
태스크릿은 드라이버 레벨에서 Soft IRQ 서비스를 등록해 쓸 수 있는 인터페이스입니다.

다른 관점으로는 태스크릿은 동적인 Soft IRQ 서비스라고 볼 수 있습니다.
태스크릿을 Soft IRQ 태스크릿 서비스에 등록하면 태스크릿 서브 서비스로 동작합니다.

리눅스 커널에서는 다음과 같은 Soft IRQ 서비스가 있으며 각각 종류는 softirq_to_name에서 확인할 수 있습니다. 
[https://elixir.bootlin.com/linux/v4.19.30/source/kernel/softirq.c]
const char * const softirq_to_name[NR_SOFTIRQS] = {
"HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "IRQ_POLL",
"TASKLET", "SCHED", "HRTIMER", "RCU"
};

softirq_to_name 전역 변수에 지정된 Soft IRQ 서비스 중 "TASKLET"이 태스크릿 인터페이스입니다.

또한 리눅스 커널에서는 다음과 같은 Soft IRQ 서비스가 있으며 각각 서비스 핸들러 함수는 softirq_vec 배열에서 확인할 수 있습니다. 
01  (static struct softirq_action [10]) [D:0x80C02080] softirq_vec = (
02    [0] = ((void (*)()) [D:0x80C02080] action = 0x80122888 = tasklet_hi_action),
03    [1] = ((void (*)()) [D:0x80C02084] action = 0x80181270 = run_timer_softirq),
04    [2] = ((void (*)()) [D:0x80C02088] action = 0x80614684 = net_tx_action),
05    [3] = ((void (*)()) [D:0x80C0208C] action = 0x80615AB0 = net_rx_action),
06    [4] = ((void (*)()) [D:0x80C02090] action = 0x804279B0 = blk_done_softirq),
07    [5] = ((void (*)()) [D:0x80C02094] action = 0x0 = ),
08    [6] = ((void (*)()) [D:0x80C02098] action = 0x8012299C = tasklet_action),
09    [7] = ((void (*)()) [D:0x80C0209C] action = 0x801588EC = run_rebalance_domains),
10    [8] = ((void (*)()) [D:0x80C020A0] action = 0x0 = ),
11    [9] = ((void (*)()) [D:0x80C020A4] action = 0x8017ABC4 = rcu_process_callbacks))

08 번째 줄 6 번째 배열 인덱스에 있는 tasklet_action() 함수가 태스크릿 서비스 핸들러 함수입니다.

다음 그림은 태스크릿 전체 흐름도입니다.
 
[태스크릿 전체 실행 흐름도]


태스크릿은 Soft IRQ 서비스 중 하나이므로 이전 절에 배웠던 Soft IRQ 서비스 실행 흐름도와 거의 비슷합니다. 

[1] 단계: Soft IRQ 서비스 요청
태스크릿 서비스를 요청합니다. tasklet_schedule() 함수에서 raise_softirq_irqoff() 함수를 호출합니다.

[2] 단계: Soft IRQ 서비스 실행
Soft IRQ 서비스 중 하나인 태스크릿 서비스 핸들러 tasklet_action() 함수를 실행합니다. 여기서 태스크릿에 등록한 태스크릿 핸들러 함수가 호출됩니다.

[3] 단계: ksoftirqd 스레드 깨움
__do_softirq() 함수에서 실행이 오래 걸려 태스크릿 서비스 핸들러를 실행 못하면 ksoftirqd 스레드를 깨웁니다.

[4] 단계: kosoftirqd 스레드 실행
ksoftirqd 스레드에서 Soft IRQ 서비스를 실행합니다.

다음 그림을 보면 태스크릿이 무엇인지 더 쉽게 이해할 수 있습니다.
 
[Soft IRQ 서비스 중 태스크릿 세부 구조]

Soft IRQ 서비스 이름을 softirq_to_name[NR_SOFTIRQS] 배열을 참고해 나열했습니다.
이 중 TASKLET 이란 Soft IRQ 서비스를 볼 수 있습니다. 이는 전체 Soft IRQ 서비스 중 하나입니다.

TASKLET Soft IRQ 아랫 부분을 보면 태스크릿A, 태스크릿B 그리고 태스크릿C가 있습니다.
이번 절에서 다루는 내용은 태스크릿A~태스크릿C 을 TASKLET Soft IRQ 서비스에 등록해 각 태스크릿 핸들러 함수가 호출되는 과정입니다.

태스크릿 자료구조 알아보기

태스크릿을 표현하는 자료구조는 struct tasklet_struct이며 선언부는 다음과 같습니다. 
[https://elixir.bootlin.com/linux/v4.19.30/source/include/linux/interrupt.h]
01 struct tasklet_struct
02 {
03 struct tasklet_struct *next;
04 unsigned long state;
05 atomic_t count;
06 void (*func)(unsigned long);
07 unsigned long data;
08 };

struct tasklet_struct *next;
   태스크릿으로의 포인터입니다.
   
unsigned long state;
태스크릿 상태를 담고 있으며 태스크릿 세부 제어를 위해 씁니다.

state 필드는 다음에 선언된 플래그 중 하나를 저장합니다.   
[https://elixir.bootlin.com/linux/v4.19.30/source/include/linux/interrupt.h]   
enum
{
TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */
TASKLET_STATE_RUN /* Tasklet is running (SMP only) */
};

TASKLET_STATE_SCHED는 태스크릿이 실행을 위해 스케줄링, TASKLET_STATE_RUN는 태스크릿이 실행 중인 상태입니다.

atomic_t count; 
태스크릿 레퍼런스 카운터이며 태스크릿을 초기화하는 tasklet_init() 함수에서 0으로 설정됩니다. count는 태스크릿 실행 여부를 판단하는 중요한 필드입니다. 반드시 0 이어야만 태스크릿을 실행합니다.

void (*func)(unsigned long);
태스크릿 핸들러 함수입니다.

tasklet_init() 함수를 호출할 때 2 번째 인자로 핸들러 함수를 등록합니다.
[https://elixir.bootlin.com/linux/v4.19.30/source/include/linux/interrupt.h]
extern void tasklet_init(struct tasklet_struct *t,
 void (*func)(unsigned long), unsigned long data);

unsigned long data;
태스크릿 핸들러 함수에 전달되는 매개인자입니다.

* 강의 동영상도 있으니 같이 들으시면 좋습니다.





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


# Reference(인터럽트 후반부 처리)








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




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


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


 



핑백

덧글

  • 역시나 2020/04/08 00:01 # 삭제 답글

    역시나 잘봤습니다 .감사합니다.
  • AustinKim 2020/04/08 08:26 #

    감사합니다.
    즐거운 하루 되십시오.

    Thanks,
    Austin Kim
댓글 입력 영역