커널 동기화 기초

from Study/System 2009/02/15 16:02 view 28806
  1. 커널 동기화 ?

    • 메모리를 공유하는 응용 프로그램은 항상 동시적인 접근으로부터 공유된 자원을 보호해야 한다.
    • 다수의 실행중인 스레드가 동시에 데이터를 변경할 경우 다른 스레드가 변경한 부분을 또 다른 스레드가 잘못 덮어써버릴 가능성이 있다.
    • 멀티프로세싱, 선점형 스케줄링 환경에서는 다양한 동시성 문제가 발생할 수 있다.


  2. Critical Region(위험구역) and Race Condition (경쟁 상태)

    • 위험구역이란 공유된 데이터를 접근하여 조작하는 코드 부분을 가리킨다. 원자적 실행을 보장해야 한다.
    • 경쟁상태란 스레드들이 위험구역에 들어가기 위해 경쟁하는 상태.


  3.  락킹(Locking)

    • 한번에 오직 하나의 스레드만이 공유하는 자료구조를 조작할 수 있다는 것을 확실할 방법.
    • 특별한 구역에서 다른 스레드가 동작하고 있을 때 해당 자료구조를 접근하지 못하게 하는 방법.
    • 락은 동시성을 방지하여 경쟁상태로부터 큐를 보호할 수 있다.

      1. 스레드는 방에 들어서면서 방문을 잠근다. 공유 데이터의 사용이 끝나면 스레드는 자물쇠를 열고 방을 떠난다.
      2. 만약 다른 스레드가 방문에 도착했을 때 문이 잠겨져 있다면, 안에 있는 스레드가 문을 열고 나올 때까지 기다린 후에 방에 들어가게 된다.
      3. 스레드는 락을 잠그고, 락은 데이터를 보호한다.


  4. 동시성

    •  프로그램들이 선점되면서 스케줄링 된다는 사실에서 비롯된다. 어떤 프로세스가 위험지역에 있을 때 비자발적으로 선점돼 버리는 일이 발생할 수 있다.

      • 유사동시성(peudo-concurrency) - 실제로는 동시에 발생하지 않지만 서로 엇갈려서 실행돼 마치 동시에 실행되는 것과 같은 효과가 발생.
      • 진정한동시성(true-concurrency) - 대칭형 멀티프로세싱 시스템에서 두 프로세스는 정확히 가튼 시간에 하나의 위험지역에 진입 할 수 있다.
    • 커널에서의 동시성의 원인

      1. 인터럽트 - 비동기적으로 어느때나 발생하여 현재 실행중인 코드를 중단시킨다.
      2. softirq와 태스크릿 - 커널은 현재 동작중인 코드를 중단하기 위해 거의 언제라도 softirq나 태스크릿을 레이즈하거나 스케줄할 수 있다.
      3. 커널 선점 - 커널도 선점형이므로, 커널에 있는 한 태스크가 다른 태스크를 선점할 수 있다.
      4. 유저공간에서의 휴면과 동기화 - 커널의 태스크는 휴면할 수 있으며 따라서 스케줄러가 새로운 프로세스를 실행하게 된다.
      5. 대칭형 멀티프로세싱 - 2개 이상의 프로세서가 코드를 동시에 실행할 수 있다.
    • 동시성으로 인해 문제가 발생되는 경우 (락이 없다면..) : 경쟁상태가 발생

      1. 커널에서 어떤 자원을 조작하고 있는 도중에 인터럽트가 발생하여 같은 자원에 접근하는 경우.
      2. 커널이 공유 자원을 사용하고 있는 동안 커널 코드가 선점되는 경우.
      3.  위험지역을 실행하는 도중 커널 코드가 휴면하는 경우.
      4. 두 프로세서가 동시에 공유데이터에 접근하는 경우.


  5.  보호영역의 결정

    • 동시에 접근될 수 있는 모든 코드는 보호가 필요로 하므로, 사실 보호가 필요없는 코드를 먼저 찾아내는 법도 있다.

      1. 특정스레드에 로컬한 데이터가 있을 경우.( 로컬자동변수, 스택에서만 존재하는 자료구조들.. )
      2. 특정 태스크에 의해서만 사용되는 데이터.
    • 보호영역의 선정 ( 커널의 거의 모든 전역 데이터와 공유 데이터는 어떠한 형식으로든 동기화. )

      1. 데이터가 전역적인가 ? 다른 스레드가 이 데이터에 접근 가능한가?
      2. 데이터가 프로세스 컨텍스트와 인터럽트 컨텍스트간에 공유되는가?
      3. 데이터를 사용하는 도중 프로세스가 선점되는 경우, 새로 스케줄된 프로세스가 같은 데이터에 접근하는가?
      4. 현재 프로세스가 휴면(or 블록)하는 경우가 있는가? 만약 그렇다면 휴면(블록)시 공유 데이터가 어떤 상태에 놓이게 되는가?
      5. 다른 곳에서 이 데이터가 해제되지 않으려면 어떻게 해야 하는가?
      6. 이 함수가 다른 프로세서에서 호출되면 어떤 일이 벌어지는가?


  6. 데드락(Deadlock)

    • 어떠한 스레드도 더 이상 진행할 수 없는 상태

      • 각 스레드가 어떤 자원을 얻으려 대기하지만 이미 모든 자원의 락이 잡혀있을 때 발생한다. 모든 스레드가 서로에 대해 대기하므로 이미 잡고 있는 자원을 해제할 수도 없다.
    • 셀프 데드락(self-deadlock) 이란  어떤 스레드가 자기 자신이 이미 잡고 있는 락을 다시 얻으려 시도할려고 할때 발생.
    •  죽음의 포옹(deadly embrace) or ABBA 데드락 이란 2개의 스레와 2개의 락이 있는 경우 발생.

      • 스레드1이 락 A를 얻음 / 스레드2가 락 B를 얻음
      • 스레드1이 락 B를 얻으려 함 / 스레드2가 락 A를 얻으려 함
      • 스레드1이 락 B에 대해 대기 / 스레드2가 락 A에 대해 대기
    • 데드락 방지

      1. 중첩된 락은 반드시 같은 순서로 잠겨져야 한다. 죽음의 포옹을 방지.

        • 서로 다른 구조체를 보호하는 cat, dog, fox 라는 3개의 락이 있을 때 어떤 함수가 cat->dog->fox 순서로 접근을 하였다.
        • 다른 모든 함수 역시 같은 순서로 락들을 잠가야 한다.
      2. 기아현상(starvation)을 방지해야 한다. 코드가 종료하는가를 되짚어 봐야 한다. 어떠한 코드도 무한대기가 일어나서는 안된다.!

        • 락이 풀리기를 대기중인 스레드들은 적당한!! 시간에 락을 얻을 수 있어야만 한다.
      3. 같은 락을 두 번 잠그지 않아야 한다.( 리눅스에서는 재귀적 락을 제공하지 하는다. )
      4. 락은 최대한 단순하게 설계해야 한다.


  7. 경쟁과 확장성

    • 현재 사용되고 있는 어떤 락을 다른 스레드가 얻으려 하는 상황을 락경쟁(Lock Contention) 혹은 경쟁이라고 한다.

      • 경쟁이 심한 락일수록 시스템 성능 저하에 더 큰 영향을 미친다.
    • 확장성이란 어떤 시스템이 얼마나 잘 확장될 수 있는가를 가리킨다.
    • 락킹의 세세함(granularity) 이란 그 락이 보호하는 데이터의 크기를 고려하는 것을 의미한다.
    • 정확하지않은(coarse)락은 많은 양의 데이터, 전체 서브시스템의 자료구조를 보호하는 경우이다.

      • 락경쟁이 심할 경우 확장성의 저하로 이어진다.
    • 매우 촘촘한(fine grained)락은 매우 적은 양의 데이터, 큰 구조체에 속한 하나의 항목만을 보호한다.

      • 충분한 락 경쟁이 없는 경우 소모적인 부하로서 작용한다.

이 글은 스프링노트에서 작성되었습니다.