Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

11206
629
98793


[리눅스커널] 동기화: 스핀락(spinlock)을 쓰는 예제 코드 살펴보기 9장. 커널동기화(스핀락/뮤텍스)

스핀락을 표현하는 구조체를 확인했으니 스핀락을 어떤 방식으로 획득하고 해제하는지 살펴보겠습니다. 예제 코드를 보기 전에 spin_lock() 함수와 spin_unlock() 함수의 선언부를 소개합니다.

이번에는 스핀락을 획득할 때 쓰는 spin_lock()와 함수의 선언부를 보겠습니다.
static __always_inline void spin_lock(spinlock_t *lock);

입력 인자는 포인터 타입 lock 변수이며 spinlock_t 구조체입니다. 함수 선언부가 void이니 반환 값은 없습니다.


__always_inline 매크로로 선언했으니 커널 함수 내에서 자주 호출되는 함수임을 알 수 있습니다.


다음은 스핀락을 해제할 때 쓰는 spin_unlock()와 함수의 선언부를 봅시다.
static __always_inline void spin_unlock(spinlock_t *lock);

spin_lock() 함수와 마찬가지로, 입력 인자는 포인터 타입 lock 변수이며 spinlock_t 구조체입니다. 함수 선언부가 void이니 반환 값은 없습니다.

이전 절에서 살펴봤듯 임계 영역에 한 개 프로세스만 접근하려면 임계 영역 코드 구간을 보호해야 합니다. 이 코드 구간을 spin_lock() 함수와 spin_unlock() 함수로 감싸는 것입니다.

이어서 스핀락을 쓰는 예제 코드를 보겠습니다.
[https://elixir.bootlin.com/linux/v4.19.30/source/kernel/kthread.c]
01 struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
02     void *data, int node,
03     const char namefmt[],
04     va_list args)
05 {
06 DECLARE_COMPLETION_ONSTACK(done);
07 struct task_struct *task;
08 struct kthread_create_info *create = kmalloc(sizeof(*create),
09      GFP_KERNEL);
...
10 spin_lock(&kthread_create_lock);
11 list_add_tail(&create->list, &kthread_create_list);
12 spin_unlock(&kthread_create_lock);
13
14 wake_up_process(kthreadd_task);
 
10번째 줄 코드에서 spin_lock() 함수를 호출해 스핀락을 획득하고 12번째 줄에서는 스핀락을 해제합니다. 

이제 다음 질문을 스스로 던지면서 코드를 분석해볼까요? 

    임계영역은 어느 코드 구간인가?
 
11번째 줄 코드로 kthread_create_list 연결 리스트에 접근하는 동작입니다. 

    임계영역을 스핀락으로 보호하는 이유는 무엇인가?
 
__kthread_create_on_node() 함수는 커널 프로세스 생성을 요청할 때 호출됩니다. 서로 다른 CPU에서 실행 중인 프로세스가 동시 다발적으로 __kthread_create_on_node() 함수를 호출하면 11번째 줄 코드를 동시에 접근할 수 있기 때문입니다. 

"혹시 궁금한 점이 있으면 댓글로 질문 남겨주세요. 아는 한 성실히 답변 올려드리겠습니다!" 

Thanks,
Austin Kim(austindh.kim@gmail.com)

#Reference(커널 동기화)
커널 동기화 기본 개념 소개
레이스 발생 동작 확인
커널 동기화 기법 소개
스핀락
뮤텍스란
커널 동기화 디버깅


핑백

덧글

댓글 입력 영역