리눅스에서의 동기화 정리

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

제가 이 글을 쓰는 목적은

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

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


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 22269
498 spin lock 을 사용하는 이유를 알고 싶습니다. [6] 장성민 2011.04.25 16479
497 ppc에서 preempt 완벽 지원여부 아시는분? [1] 최종환 2007.02.22 16131
» 리눅스에서의 동기화 정리 [13] 홍문화 2011.04.25 16027
495 Embeded 보드에 udev 올리는 법에 관한 조언을 요청드립니다. [4] 장성민 2011.01.08 15939
494 플래시 메모리에서 FTL(Flash Translation Layer) S/W 모듈과 관련하여 문의 드립니다. [4] 남현우 2009.01.09 15867
493 create_workqueue 와 create_singlethread_workqueue 의 차이? 김영민 2010.12.24 15521
492 VMware의 Linux에 Xen 설치해서 XP 설치 가능?? [5] 무명 2009.01.17 15513
491 u-boot 소스 분석에서 궁금한 점이 있습니다. [6] 원민수 2006.06.28 15196
490 멀티 스레드를 이용한 20억번 돌기의 시간 재기 [29] 이경문 2011.07.15 15194
489 mov r0,r0 [27] 송원준 2010.05.03 15172
488 모듈오류가 나는데 이유가 뭔지 안잡히네요.. [5] 김영일 2010.11.30 14560
487 linux swap out 관련.. [1] 박은병 2009.03.05 14463
486 안드로이드 고수님들께 질문드립니다. ^^ [11] Jason 2012.10.23 14200
485 [toolchain] arm-linux-gcc [4] 김민종 2010.04.27 14094
484 i386의 i 와 386은 각각 어떤 의미인가요? [4] 이경호 2007.03.07 13685
483 thread의 상태값 [4] 송선희 2009.03.10 13568
482 kernel의 virtual address [5] file 김민종 2010.04.28 13480
481 디버거 원리.. [6] 박은병 2008.01.31 13443
480 mutex와 semaphore차이? [2] 김영민 2011.03.02 13316
479 ___reserved_mem_reserve_reg 관련 질문 [4] DEWH 2020.03.09 12866
XE Login