리눅스에서의 동기화 정리

홍문화 2011.04.25 10:30 조회 수 : 16019

제가 이 글을 쓰는 목적은

첫째, 제가 이해한 바에 대해 옳은 부분에 대해서는 선배님들의 동의를 구하고 틀린 부분에 대해서는 지적을 부탁드리기 위함입니다.

둘째, 동기화에 대해 이해 하고자 노력하는 열정적인 개발자들과 지식을 공유하기 위함입니다.


1. [UP system] 프로세스 컨텍스트간의 동기화


   semaphore, preempt_disable

   semaphore는 CS를 공유하는 프로세스 컨텍스트들을 휴면 시켜서 동기화를 달성합니다.

   preempt_disable은 CS를 공유하는 프로세스 컨텍스트들은 물론이고 다른 모든 프로세스 컨텍스트들 또한 선점을 금지시켜

   동기화를 달성합니다. CS 구간이 긴경우 semaphore를 짧은 경우 preempt_disable을 사용하는게 효율적이라 생각합니다.

  

   local_irq_disable을 사용 할 수도 있겠지만 인터럽트 컨텍스트가 없기 때문에 불필요합니다.(불가능이 아님.)

   프로세스 컨텍스트는 휴면 가능 하므로 spin_lock은 사용 불가능 합니다. (데드락 발생)


2. [UP system] 프로세스 컨텍스트와 인터럽트 컨텍스트간의 동기화

 

   local_irq_disable

   local_irq_disable은 모든 인터럽트를 금지 시키기 때문에(심지어 타이머 인터럽트에 기반한 스케줄러까지)

   CS를 공유하는 프로세스 컨텍스트와 인터럽트 컨텍스트간 동기화를 달성합니다.

  

   인터럽트는 스케줄링 대상이 아니므로 semaphore, preempt_disable로는 프로세스 컨텍스트와 동기화를 달성 할 수 없습니다.

   또한 semaphore는 휴면 가능 하므로 인터럽트 컨텍스트에서는 아예 사용이 불가능합니다.

   인터럽트 컨텍스트는 항상 프로세스 컨텍스트에 우선 하므로 spin_lock은 사용 불가능합니다. (데드락 발생)


3. [UP system] 인터럽트 컨텍스트간의 동기화

   

    local_irq_disable

    인터럽트 컨텍스트는 스케줄링 대상이 아니므로 local_irq_disable로 동기화를 달성합니다.

   

    spin_lock를 사용 할 수도 있겠지만 프로세서가 하나이기 때문에 불필요합니다.(불가능이 아님.)

    심지어 인터럽트는 우선순위에 따라 중첩이 가능하므로 spin_lock은 데드락의 원인이 됩니다.

    그래도 의미 없는 spin_lock을 사용하고자 한다면 반드시 local_irq_disable을 먼저 호출하고 락을 잡아야 합니다.


    semaphore, preempt_disable는 인터럽트 컨텍스트간의 동기화에 아무런 역할을 하지 못하며

    semaphore는 휴면 가능 하므로 인터럽트 컨텍스트에서는 아예 사용이 불가능합니다.


4. [SMP system] 프로세스 컨텍스트간의 동기화

 

    spin_lock

    프로세스 컨텍스트가 하나의 프로세서에서 유사동시성을 가짐과 동시에 다수의 프로세서에서 진정한 동시성을 가지게 됩니다.

    CS가 다수의 프로세서에 의해 공유 되므로 반드시 spin_lock을 사용해야 다수의 프로세서간에 동기화가 달성 됩니다.


    semaphore, preempt_disable

    이 두 녀석은 오직 유사 동시성에서의 동기화를 위해 사용한다고 생각합니다.

    예를 들어 A, B 두개의 프로세서가 있습니다. 그리고 CS를 공유하는 1, 2, 3, 4 네개의 태스크가 있습니다.

    어떠한 원인인지는 몰라도(로드 밸런싱을 포함한 다수의 경우가 있을 수 있겠죠.) 태스크 1, 2는 A 프로세서에서

    실행 되고 있고 태스크 3, 4은 B 프로세서에서 실행 된다고 가정 합니다. semaphore는 전역으로 하나가 생성

    되겠지만 세마포어의 대기큐는 프로세서별로 하나씩 생기게 될거라 생각합니다. 그래서 프로세서 A에서는 세마포어의

    대기큐 A에 의해 태스크 1, 2간의 동기화를 달성하고 프로세서 B에서는 세마포어의 대기큐 B에 의해 태스크 3, 4간의

    동기화를 달성 하지 않을까 합니다. 물론 태스크 (1, 2)와 (3, 4)간의 동기화는 spin_lock으로 달성 될것입니다.

   

    preempt_disable은 특정 프로세서에서의 선점을 금지 합니다. 이렇게 하여 각 프로세서별 유사 동시성을 달성 하게

    될 것입니다. 예를 들어 프로세서 A의 태스크 1, 2든 프로세서 B의 태스크 3, 4든 CS 진입 시에 preempt_disable을 호출하면

    프로세서 A의 태스크 1, 2간의 유사 동시성에 의한 동기화가 달성 되고 프로세서 B의 태스크 3, 4간의 유사 동시성에 의한

    동기화도 달성 될것입니다. 하지만 이것만으로는 프로세서간의 진정한 동시성에 의한 동기화는 달성 할 수 없으므로

    태스크 (1, 2)와 (3, 4)간의 동기화는 spin_lock으로 달성 될것입니다.


    위와 같은 정황을 고려해서 판단할 때 semaphore, preempt_disable은 유사 동시성에서의 동기화를 위해서만 사용 될거라는

    결론을 개인적으로 내려봅니다. SMP에서 프로세스 컨텍스트간의 완벽한 동기화를 위해서는다음과 같은 코드 모양이

    될거라고 봅니다.


    1)                                                                          2)

    preempt_disable    -->유사 동시성 동기화                   semaphore_wait      -->유사 동시성 동기화

    spin_lock              -->진정한 동시성 동기화                spin_lock                -->진정한 동시성 동기화


         CS                                                                         CS  


    spin_unlock                                                            spin_unlock

    preempt_enable                                                      semaphore_post


    이렇게 코드가 작성 된다면 SMP에서 UP로 갈 경우 spin_lock만 걷어내면 될것입니다.


5. [SMP system] 프로세스 컨텍스트와 인터럽트 컨텍스트간의 동기화


    local_irq_disable + spin_lock


    local_irq_disable은 로컬 프로세서의 모든 인터럽트를 금지 하므로 유사 동시성 에서의 프로세스 컨텍스트간의

    동기화를 달성함과 동시에 프로세스 컨텍스트와 인터럽트 컨텍스트간의 동기화를 달성 할 수 있습니다.

    하지만 인터럽트는 다른 프로세서에의해 핸들링 될 수 있으므로 반드시 spin_lock을 더해줘야 합니다.

    이 조합을 하나의 함수로 처리한 것이 spin_lock_irqsave(), spin_lock_irqstore()입니다.

    UP에서와 마찬가지로 유사동시성에서의 데드락을 방지하기위해 반드시 인터럽트를 먼저 금지하고 락을 잡아야 합니다.


    물론 preempt_disable을 사용해 프로세스 컨텍스트간의 동기화를 해결 할 수 있겠지만

    local_irq_disable이 이를 해결 해주므로 사용 할 필요가 없겠습니다. 또한 semaphore는 휴면 가능 하므로

    인터럽트 컨텍스트에서는 아예 사용이 불가능합니다.

   

                                                           

  preempt_disable    -->프로세스 컨텍스트간의 동기화 (유사 동시성) => 불필요함.

  local_irq_disable    -->프로세스 컨텍스트간의 동기화 + 프로세스 컨텍스트와 인터럽트 컨텍스트간의 동기화 (유사 동시성)           

  spin_lock              -->진정한 동시성 동기화               


       CS                                                                       


  spin_unlock

  local_irq_enable                                            

  preempt_enable                                                    


6. [SMP system] 인터럽트 컨텍스트간의 동기화


  local_irq_disable + spin_lock


  local_irq_disable은 유사 동시성에서의 동기화를 위해 사용하는 것이며 (단일 프로세서에서의 인터럽트 컨텍스트간의 동기화)

  진정한 동시성에서의 동기화는  spin_lock을 통해 달성 됩니다. 또한 유사 동시성에서의 데드락을 방지하기 위해 반드시

  인터럽트를 먼저 금지하고 락을 잡아야 합니다.

  semaphore, preempt_disable는 인터럽트 컨텍스트간의 동기화에 아무런 역할을 하지 못하며

  semaphore는 휴면 가능 하므로 인터럽트 컨텍스트에서는 아예 사용이 불가능합니다.

   


쓰다보니 내용이 상당히 길어진것 같습니다.

선배님들의 많은 조언 부탁 드립니다.

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 프로그래밍 관련 Q&A 게시판 입니다. woos 2016.04.09 22250
158 x86에서 ZONE_DMA 영역의 사용 [1] 홍문화 2011.05.02 58311
157 CPU bound 와 I/O Bound 구분 김영민 2011.04.26 9374
156 커널 "BUG: scheduling while atomic" 문제에 대해 질문 드립니다. 육상호 2011.04.25 9743
155 가상메모리 관련 초보 질문 [2] Jason 2011.04.25 10571
» 리눅스에서의 동기화 정리 [13] 홍문화 2011.04.25 16019
153 barrier() 에 대한 설명좀 부탁드립니다. [1] 장성민 2011.04.25 10009
152 spin lock 을 사용하는 이유를 알고 싶습니다. [6] 장성민 2011.04.25 16478
151 Cache에 대한 초보적인 질문 .... [9] Jason 2011.04.19 12046
150 /etc/exports 파일이 없어졌어요.. 이사갔나?? [3] 김영일 2011.04.18 7846
149 RT task 에 관한 질문입니다. [3] 송창인 2011.04.18 7208
148 메모리와 페이지 테이블에 대해 질문 드립니다. [1] pororo 2011.04.17 9048
147 안드로이드 system 폴더안의 파일을 인식못하는데.. [5] 김영일 2011.04.14 69699
146 시그널을 통하여 주기 태스트를 하는데 주기가 깨집니다. 고수님들 많은 조언 부탁 드립니다. [3] 이승훈 2011.04.13 4790
145 리눅스의 스케쥴링에 따른 priority는 어떻게 설정해주나요? [5] 심우진 2011.04.12 8539
144 가상 주소 공간에 대해서 질문이 있습니다~ 정재훈 2011.04.12 8037
143 signal에 대한 질문입니다 많은 조언 부탁드립니다 ㅠㅠ [19] 송창인 2011.04.06 8597
142 HP-UX 링크 옵션 질문입니다. [6] 조운현 2011.04.06 8572
141 최근 arm linux kernel mailing 가입하신분 있나요? 정준석 2011.03.30 5037
140 emacs에서 cscope-find-global-definition과 find TAG [3] 이승한 2011.03.30 7524
139 스터디 첫날 모임에 대해서 문의드립니다. [1] 이원철 2011.03.23 4762
XE Login