Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

8200
629
98815


[리눅스커널] 동기화: 스핀락(spinlock) 처리 흐름도 알아보기 9장. 커널동기화(스핀락/뮤텍스)

스핀락을 분석할 때 스핀락을 획득한 후 임계 영역을 실행할 때 바뀌는 자료구조를 함께 파악하는 것이 중요합니다. 

이번에 스핀락을 관리하는 spinlock_t 구조체를 다시 보면서 스핀락 자료 구조를 설명을 드리겠습니다.
(spinlock_t *) (spinlock_t*)0xb7e0eb00 
  (struct raw_spinlock) rlock = (
    (arch_spinlock_t) raw_lock = (
      (u32) slock = 0x134C134C,
      (struct __raw_tickets) tickets = (
        (u16) owner = 0x134C,
        (u16) next = 0x134C))))

위와 같이 spinlock_t 구조체는 서로 다른 아키텍처에서 스핀락를 처리하도록 다른 구조체로 캐스팅됩니다. 그런데 라즈비안은 ARMv7 아키텍처를 적용하므로 spinlock_t 구조체의 실체는 struct __raw_tickets 입니다.

struct __raw_tickets 구조체 필드를 보면 owner와 next가 있습니다.

    스핀락은 owner와 next 2개 필드만으로 스핀락 동작을 처리합니다.

앞으로 스핀락 세부 동작을 설명할 때 스핀락 자료 구조는 owner와 next로 언급하겠습니다.


스핀락을 획득하고 해제하는 전체 흐름도 파악하기

이번에는 스핀락을 획득하고 해제할 때 다음 전체 실행 흐름도를 보면서 동작 원리를 배워볼까요? 
 
[그림 9.6] 스핀락을 획득하고 해제할 때 동작 흐름도

먼저 위 그림에서 쓴 용어부터 소개하겠습니다. 

그림 가운데에 있는 스핀락 지역 변수부터 알아봅시다.
스핀락을 획득하려는 프로세스 스택 공간에서 실행하는 스핀락 값입니다. 지역 변수이니 각각 프로세스 스택 공간에서 실행합니다. 만약 A와 B란 프로세스가 있다고 가정하면 A와 B 프로세스별로 각각 스핀락 지역변수가 있는 것입니다.

다음으로 그림 오른쪽 부분에 보이는 스핀락 인스턴스입니다.
특정 메모리 공간에 있는 스핀락 자료구조이며 전역 변수와 비슷한 개념입니다. 스핀락 인스턴스를 A나 B란 프로세스가 같은 시간에 읽으면 스핀락 인스턴스 값은 같습니다.

스핀락 코드를 분석할 때 스핀락 인스턴스와 스핀락 지역 변수의 개념을 그리면서 보면 더 쉽게 이해할 수 있습니다. 

다음으로 단계별 스핀락 세부 동작을 알아봅시다. 스핀락 획득 이전에 스핀락 인스턴스의 owner와 next가 각각 0x134C이라고 가정합니다.

1. 스핀락 획득

spin_lock() 함수를 실행하면 스핀락 획득을 시작합니다.
  1.1 스핀락 인스턴스의 owner와 next 값을 스핀락 지역 변수 owner와 next에 저장합니다.
  스핀락 인스턴스의 next를 +1 증감합니다.

1.2 spin_lock() 함수를 처음 실행했을 때 스핀락 인스턴스의 owner와 next가 각각 
0x134C으로 같으니 스핀락을 다른 프로세스가 획득한 적이 없다고 판단합니다.

따라서 바로 스핀락을 획득합니다.

2. 임계영역

스핀락을 획득했으니 spin_lock() 함수 실행을 종료합니다. 이후 임계 영역에서 코드 실행을 합니다. 임계 영역 구간에서 스핀락 인스턴스 값은 다음과 같습니다.
owner: 0x134C
next:  0x134D  
 
위 조건에서 만약 다른 CPU에서 실행 중인 프로세스가 같은 임계영역에 접근하려고 스핀락 획득을 시도하면 어떻게 동작할까요?  

    스핀락 인스턴스의 next가 owner보다 1보다 크니 spin_lock() 함수 내부에서 next가 
    owner와 같을 때까지 기다립니다. 

3. 스핀락 해제

임계 영역이 끝나는 시점에 spin_unlock() 함수를 호출하면 획득한 스핀락을 해제할 수 있습니다. spin_unlock() 함수는 스핀락 인스턴스의 owner를 +1 증감합니다.

스핀락을 해제 한 후 스핀락 인스턴스 값은 다음과 같습니다.
owner: 0x134D
next:  0x134D  

owner와 next가 같은 값입니다. 이 결과는 다음과 같이 해석할 수 있습니다. 

    스핀락을 획득한 적이 없다. 

스핀락을 획득을 기다리다가 스핀락을 획득하는 과정 알아보기

이번에는 누군가 스핀락을 획득한 상태에서 스핀락을 기다리는 동작을 그려 봅시다. 이전 그림에서 2단계 임계 영역 코드 실행 도중 스핀락을 획득하는 상황입니다.
 
   [그림 9.7] 스핀락을 기다리다가 획득할 때 동작 흐름도

스핀락을 획득을 기다리다가 스핀락을 획득하는 실행 흐름은 그림 왼쪽 부분과 같이 3단계로 분류할 수 있습니다.

스핀락 획득 시도

이미 스핀락을 누군가 획득했으니 spin_lock() 함수 호출 전 스핀락 인스턴스는 다음 값과 같습니다. 
owner: 0x134C
next:  0x134D 

스핀락 인스턴스는 어느 프로세스에서 접근할 수 있는 전역 변수와 같은 상태입니다.

스핀락 지역변수 owner, next에 스핀락 인스턴스 owner, next를 저장합니다. 스핀락 인스턴스 next를 +1만큼 증감합니다.

Busy-Wait

스핀락 지역변수 owner, next가 같지 않으니 스핀락을 누군가 획득한 상태라 판단합니다. 다른 프로세스가 스핀락을 획득하고 임계 영역을 실행 중인 상태입니다. 스핀락 인스턴스를 계속 읽으면서 스핀락 인스턴스 중 owner가 0x134D로 바뀔 때까지 무한 루프를 돌며 기다립니다.

그런데 다른 프로세스가 스핀락을 해제하면 스핀락 인스턴스는 어떻게 바뀔까요? 스핀락 인스턴스의 owner가 +1만큼 증감해서 0x134D가 됩니다.


이전 절 커널 동기화 기법을 소개할 때 화장실에 이미 누군가 있으면 밖에서 계속 기다린다고 설명했습니다. 바로 이 동작입니다.

스핀락 획득

다른 프로세스가 스핀락을 해제했으니 스핀락 인스턴스 owner가 0x134D로 증감합니다.
스핀락이 해제되기를 계속 기다린 프로세스의 스핀락 지역 변수 next가 0x134D입니다.

바로 스핀락을 획득하고 spin_lock() 함수를 종료한 후 임계 영역을 실행합니다.

여기까지 배운 스핀락을 획득하는 과정을 정리해볼까요?
첫째, 스핀락을 이미 획득했는지 어떻게 판단할까?
스핀락 인스턴스 next와 owner 필드를 확인하면 된다.

둘째, 스핀락을 획득한 후 바뀌는 자료구조는 무엇인가?
스핀락 인스턴스 next를 +1만큼 증감한다.

셋째, 획득한 스핀락을 해제한 후 바뀌는 자료구조는 무엇인가?
스핀락 인스턴스 owner를 +1만큼 증감한다.

스핀락 동작에 대해서 전체 흐름을 알아봤습니다. 다음 소절에서는 스핀락 함수 코드를 직접 분석 하면서 동작을 알아봅니다.

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

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

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


핑백

덧글

댓글 입력 영역