Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

10206
629
98792


[라즈베리파이] 동기화 - 커널 동기화 기법 소개 9장. 커널동기화(스핀락/뮤텍스)

이전 시간에 Race가 발생하는 3가지 대표적인 상황을 확인했습니다. 이어서 이번에 커널 동기화 기법을 소개하고 그 특징을 알아봅니다.

이전에 소개했던 그림을 다시 보겠습니다. 임계 영역에 A와 B 프로세스가 접근하는 상황입니다.
 
       
두 커널 동기화 기법인 스핀락과 뮤텍스의 차이점을 비교하면서 동기화 기법에 대해 살펴보겠습니다.

스핀락과 뮤텍스의 가장 큰 차이점은 위 그림 [6] 번호 밑 박스에 표시돼 있습니다. 이미 락(Lock)을 다른 프로세스가 획득하고 있을 때 기다리는 방법입니다. 

스핀락은 다른 일(스케줄링)을 안 하고 화장실 밖에서 계속 기다립니다. 이를 Busy-Wait라고 설명합니다. 뮤텍스는 자신을 대기열에 등록하고 자신을 UNINTERRUPTIBLE 상태로 바꾼 다음 휴면에 들어갑니다. 따라서 다른 프로세스가 일을 할 수 있는 겁니다.

뮤텍스는 다른 프로세스가 뮤텍스를 획득한 상태면 휴면에 들어갑니다. 따라서 인터럽트나 Soft IRQ 컨택스트에서 뮤텍스를 쓰면 안 됩니다. 인터럽트나 Soft IRQ는 짧고 굵게 빨리 코드를 실행해야 하기 때문입니다. 

두 번째로 다른 프로세스가 락을 기다리고 있을 때 화장실에서 A가 나왔을 때 하는 행동이 서로 다릅니다. 위 그림 8.1을 봅시다.

B는 바로 스핀락을 획득한 다음에 화장실에 들어갑니다. B가 화장실 밖에서 다른 일은 안 하고 계속 기다렸으니 빨리 스핀락을 획득할 수 있는 겁니다.

뮤텍스 경우는 다릅니다. A가 화장실에서 나온 다음에 밖에서 기다리는 사람이 있는지 확인합니다. [8.1] 단계에서 A는 대기열을 보고 B가 화장실 밖에서 기다리고 있다는 사실을 알게 됩니다. 친절하게 A는 B를 깨웁니다. 화장실 밖에서 휴면에 들어간 B란 사람은 깨어난 후 자신이 화장실에 들어갈 차례라고 판단하고 뮤텍스를 획득하고 화장실에 들어갑니다.

두 동기화 기법의 가장 큰 차이점을 살펴봤습니다. 이 차이점을 파악하고 3가지 특징을 유추할 수 있습니다.
  1. 스핀락은 코드 복잡도가 낮습니다. 스핀락을 누군가 획득하고 있으면 밖에서 계속 기다리기 때문입니다. 
  2. 뮤텍스는 스핀락에 비해 코드 복잡도가 높습니다. 다른 프로세스가 뮤텍스를 획득하면 휴면에 들어가고 깨어나는 추가 동작을 하기 때문입니다.
  3. 스핀락은 아키텍처에 의존적인 반면 뮤텍스는 아키텍처에 의존적이지 않은 리눅스 커널 함수로 구현됐습니다.

스핀락과 뮤텍스 동작의 3가지 가장 큰 차이점을 알아봤습니다. 두 기법의 세부적인 차이점을 비교하면서 두 기법에 대해 살펴봅시다.

자물쇠가 잠겼는지 알아보는 방법
스핀락
스핀락을 표현하는 구조체에서 owner와 next 멤버가 0x134C로 같으면 스핀락을 잠근 적이 없다고 판단합니다. 바로 스핀락을 획득합니다.
      (arch_spinlock_t) raw_lock = (
        (u32) slock = 0x134C134C,
        (struct __raw_tickets) tickets = (
          (u16) owner = 0x134C,
          (u16) next = 0x134C))))
뮤텍스
뮤텍스 구조체에서 owner 멤버가 0x0인지 확인합니다. 다음과 같이 owner 멤버가 다른 프로세스의 태스크 디스크립터 주소를 담고 있으면 이미 다른 프로세스가 뮤텍스를 획득했다고 판단합니다.
(struct mutex *) (struct mutex *)0xb000c000 = 0xB000C000 -> (
    (atomic_long_t) owner = ((int) counter = 0xB0C0D000),
    (spinlock_t) wait_lock = ((struct raw_spinlock) rlock,
      (struct list_head *) next = 0x0,
      (struct list_head *) prev = 0x0))

자물쇠를 잠그는 방법
스핀락
 스핀락을 표현하는 구조체 멤버 중 next를 +1만큼 증감합니다.
      (arch_spinlock_t) raw_lock = (
        (u32) slock = 0x134C134C,
        (struct __raw_tickets) tickets = (
          (u16) owner = 0x134C,
          (u16) next = 0x134D))))
뮤텍스
뮤텍스 구조체에서 owner 멤버에 뮤텍스를 획득한 프로세스의 태스크 디스크립터 주소를 저장합니다.
  (struct mutex *) (struct mutex *)0xb000c000 = 0xB000C000 -> (
    (atomic_long_t) owner = ((int) counter = 0xB0C0D000),
    (spinlock_t) wait_lock = ((struct raw_spinlock) rlock,
      (struct list_head *) next = 0x0,
      (struct list_head *) prev = 0x0))

자물쇠를 푸는 방법
스핀락
스핀락을 표현하는 구조체 tickets 멤버 중 owner를 +1만큼 증감합니다.
      (arch_spinlock_t) raw_lock = (
        (u32) slock = 0x134C134C,
        (struct __raw_tickets) tickets = (
          (u16) owner = 0x134D,
          (u16) next = 0x134D))))

뮤텍스
뮤텍스 구조체 struct mutex owner 멤버를 0x0으로 업데이트합니다.
  (struct mutex *) (struct mutex *)0xb000c000 = 0xB000C000 -> (
    (atomic_long_t) owner = ((int) counter = 0x0),
    (spinlock_t) wait_lock = ((struct raw_spinlock) rlock,
    (struct list_head) wait_list = (
      (struct list_head *) next = 0x0,
      (struct list_head *) prev = 0x0))

자물쇠가 이미 잠겨있을 때 어떻게 동작할까?
스핀락
스핀락을 표현하는 구조체에서 next가 owner보다 +1만큼 크면 스핀락을 누군가 잡고 있다고 판단합니다.
      (arch_spinlock_t) raw_lock = (
        (u32) slock = 0x134C134C,
        (struct __raw_tickets) tickets = (
          (u16) owner = 0x134C,
          (u16) next = 0x134D))))

뮤텍스
뮤텍스 구조체 struct mutex 멤버인 wait_list에 등록하고 잠들어 버립니다.
  (struct mutex *) (struct mutex *)0xb000c000 = 0xB000C000 -> (
    (atomic_long_t) owner = ((int) counter = 0xB0C0D000),
    (spinlock_t) wait_lock = ((struct raw_spinlock) rlock,
    (struct list_head) wait_list = (
      (struct list_head *) next = 0xb33F000,  //<<--
      (struct list_head *) prev = 0xb33F000))

스핀락을 획득하기 위해 프로세스는 다른 일을 하지 않고 계속 기다립니다. 이를 Busy-Wait라고 합니다.

커널 동기화 기법의 대표 선수인 스핀락과 뮤텍스에 대해 알아봤습니다. 다음 시간에 스핀락을 더 살펴보겠습니다.


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

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

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

 

핑백

덧글

댓글 입력 영역