정보공간_1

[6기 강북 전영진] 리눅스 커널 심층 분석 #5 본문

IT 놀이터/Elite Member Tech & Talk

[6기 강북 전영진] 리눅스 커널 심층 분석 #5

알 수 없는 사용자 2014. 12. 8. 05:10

#Intro

안녕하세요. 강북멤버십 23-2기 전영진입니다.

 

이번엔 리눅스 인터럽트 후반부 처리에 대해 살펴보겠습니다.

 

#후반부 처리

후반부 처리의 역할: 인터럽트 핸들러가 처리하지 않은 모든 인터럽트 관련 처리를 수행.

( 최대한 많은 일을 후반부 처리로 덜어냄으로써 인터럽트 핸들러가 중단시킨 시스템 제어권을 가능한 빨리 돌려줄 수 있습니다. )

하지만 인터럽트 핸들러가 직접 꼭 수행해야만 하는 몇 가지 일이 있습니다.

예를 들어, 인터럽트 핸들러는 하드웨어에 인터럽트를 수신했다는 사실을 알려야 됩니다.

데이터를 하드웨어에서 복사하거나 하드웨어로 복사하는 작업이 필요할 수 있습니다.

이러한 작업들은 시간에 민감하기 때문에 인터럽트 핸들러에서 처리하는 것이 좋습니다.

이외의 거의 모든 일은 후반부 처리가 담당하는 것이 좋습니다.

전반부 처리와 후반부 처리의 방법을 항상 명확한 것은 아니지만 다음 사항을 고려하면 도움이 될 것입니다.

 

- 고려 사항 -

1.     실행 시간이 민감한 작업이라면 인터럽트 핸들러에서 처리.

2.     하드웨어와 관련된 작업이라면 인터럽트 핸들러에서 처리.

3.     다른 인터럽트가 방해해서는 안 되는 작업이라면 인터럽트 핸들러에서 처리.

4.     그 외의 작업은 후반부 처리에서 수행하는 것으로 생각.

 

#후반부 처리의 세계

인터럽트 핸들러를 통해 모든 것이 구현되는 전반부 처리와 달리 후반부 처리의 구현 방법은 여러 가지가 있습니다. 애초에 리눅스는 후반부 처리 방법으로 Bottom Half만을 제공했습니다.

이를 BH방식이라고 부르기도 하는데, 이 방식은 오래 전에 사용이 중단되었으며 2.5 개발 버전에서 완전히 제거되었습니다.

현재는 지연 작업 처리를 위한 세가지 방법으로 softirq, 태스크릿, 워크 큐가 있습니다.

 

#softirq

softirq를 직접 사용하는 경우는 드물다. 일반적으로 태스크릿을 사용해 후반부 처리를 하는 경우가 더 많지만 태스크릿이 softirq를 기반으로 만들어 졌습니다. softirq 코드는 커널 소스의 kernel/softirq.c 파일에 들어있습니다.

 

- softirq 구현

softirq는 컴파일 시에 정적으로 할당되므로, 태스크릿과 달리 softirq는 동적으로 등록하거나 제거 할 수 없습니다. softriq <linux/interrupt.h>파일에 정의된 softirq_action 구조체를 이용하여 표현합니다.

struct softirq_action{

             void (*action)(struct softirq_action *);

}

 

static struct softirq_action softirq_vec[NR_SOFTIRQS];

등록된 softirq마다 이 배열을 하나씩 사용합니다. 따라서 softirqNR_SOFTIRQS 개수만큼 등록할 수 있습니다.

 

softirq시스템에서 가장 실행시간에 민감하고 중요한 후반부 처리를 수행할 때 사용하도록 되어있습니다. 현재 직접 softirq를 사용하는 서브시스템은 네트워크와 블록장치 둘 뿐입니다. 이와 별도로 커널 타이머와 태스크릿도 softirq를 기반으로 만들어져 있습니다. 새로 softirq를 추가하고자 한다면, 왜 일반적인 태스크릿 사용으로 충분하지 않은지를 확인해봐야 합니다. 태스크릿은 동적으로 생성이 가능하고 락 사용이 덜 엄격해 사용하기가 편하면서도 괜찮은 성능을 보여줍니다. 하지만 자체적으로 효율적인 락 관리가 가능하며 실행시간이 중요한 상황이라면, softirq가 더 올바른 해법입니다.

 

#태스크릿

태스크릿은 softirq를 기반으로 만들어진 후반부 처리 방식입니다. 태스크릿의 동작과 특성은 softirq와 유사하지만 인터페이스가 더 간단하고, 락 사용 제한이 더 유연합니다.

장치 드라이버를 만들 때 softirq와 태스크릿 중 거의 항상 태스크릿을 사용합니다. softirq는 실행횟수가 빈번하고 병렬처리가 필요한 경우에만 사용합니다. 반면 태스크릿은 훨씬 광범위하게 사용되며 거의 대부분의 상황이 태스크릿으로도 충분하며 사용법도 아주 쉽습니다.

 

태스크릿도 softirq를 기반으로 만들어졌기 때문에 태스크릿도 softirq라고 할 수 있습니다. 태스크릿은 HI_SOFTIRQ, TASKLET_SOFTIRQ 두 가지 softirq를 이용합니다. 둘의 차이점은 HI_SOFTIRQ 기반의 태스크릿의 우선순위가 TASKLET_SOFTIRQ 기반의 태스크릿보다 높다는 것 뿐입니다.

일반적인 대부분 하드웨어 장치의 후반부 처리는 태스크릿을 이용해 구현하는 편이 좋습니다. 태스크릿은 동적으로 생성이 가능하며, 사용하기 편하고 빠릅니다.

 

#워크 큐

워크 큐는 지연 작업을 커널 스레드 형태로 처리합니다. 이 방식의 후반부 처리는 프로세스 컨텍스트에서 실행됩니다. 따라서 워크 큐로 지연된 작업은 통상적인 프로세스 컨텍스트의 이점을 모두 누릴 수 있습니다. 가장 중요한 점으로 스케줄링이 가능하며 휴면 상태로 전환될 수 있다는 점을 들 수 있습니다.

워크 큐는 보통 지연되는 작업이 휴면 상태 전환이 필요한 경우일 경우 사용합니다. 지연되는 작업이 휴면 상태로 전환될 필요가 없다면 softirq나 태스크릿을 사용합니다. 워크 큐의 대안으로 일반적인 커널 스레드도 있지만 커널 개발자들은 커널 스레드를 새로 만드는 것을 꺼려하기 때문에, 절대적으로 워크 큐를 선호합니다.

후반부 처리 작업을 수행하는 과정에 스케줄링이 필요한 부분이 있다면 워크 큐를 사용해야 됩니다. 워크 큐는 프로세스 컨텍스트에서 실행되며 휴면 상태로 전환이 가능한 유일한 후반부 처리 방식입니다. 많은 양의 메모리 할당이나 세마포어 할당, 블록 입출력 작업이 필요한 경우에 유용합니다. 지연 작업을 처리하는데 커널 스레드가 필요하지 않다면, 대신 탯그크릿을 사용하는 것을 검토해볼 필요가 있습니다.

 

 

 

 

#후반부 처리 방식 선정

Softirq : 설계상 최소한의 직렬화만 제공, 같은 유형의 둘 이상의 softirq가 다른 프로세서에서 동시 실행될 수 있으므로 공유 데이터를 안전하게 사용하려면 softirq 핸들러에 부가적인 처리를 해야됩니다. 실행 시간에 아주 민감하고 사용빈도가 높은 경우에 선택할 수 있는 분명히 가장 빠른 대안입니다.

 

태스크릿 : 코드가 충분히 스레드화 되어 있지 않다면 태스크릿이 Softirq보다 유용, 태스크릿은 더 간단한 인터페이스를 가지고 있으며, 같은 유형의 두 태스크릿이 동시에 실행되지 않으므로 구현 작업이 더 쉽습니다. 다중 프로세서 환경에서 softirq를 동시에 안전하게 실행 할 수 있도록 프로세서별로 변수를 사용할 준비가 되거나, 이에 준하는 대책이 마련된 경우가 아니라면 드라이버 개발자는 항상 softirq보다는 태스크릿을 우선적으로 고려해야합니다.

 

워크 큐 : 지연 작업을 프로세스 컨텍스트에서 실행해야 될 경우 가능한 후반부 처리 방식, 프로세스 컨텍스트가 필요하지 않다면, softirq나 태스크릿을 사용하는 편이 더 효율적 입니다. 워크 큐는 커널 스레드를 사용하기 때문에 컨텍스트 전환이 필요하므로 부가 비용이 가장 큽니다. 사용자 편의성의 측면에선느 워크 큐가 가장 좋습니다. 기본 events 큐를 사용하는 방법으로 가장 쉽고, 그 다음으로 태스크릿 역시 간단한 인터페이스를 가지고 있습니다. 정적으로 생성해야 하며 구현할 때 여러가지를 고려하는 softirq가 사용 편의성 측면에서 맨 나중입니다.

 

- 세 가지 후반부 처리 인터페이스 비교표 

 

 

이상으로 리눅스 인터럽트  후반부 처리인 softirq, 태스크릿, 워크 큐에 대한 포스팅을 마치겠습니다.

(Linux kernel development. 3/E 참조)