Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

80258
1323
114582


[리눅스커널] 커널동기화: 임계영역(Critical Section)과 레이스 컨디션이란 9. Synchronize(spinlock/mutex)

커널 동기화란 다음과 같이 동작 하도록 코드를 설계하거나 유지보수하는 기법을 의미합니다.
1. 어떤 함수나 특정 코드 구간을 실행할 때 1개 프로세스만 접근
2. 정해진 순서로 코드 실행

그런데 커널 동기화에 대해 제대로 파악하려면 다음 2가지 개념에 대해 알 필요가 있습니다.
  - 임계영역
  - 레이스 컨디션

이번 절에서는 커널 동기화를 이루는 기본 개념들을 소개합니다. 
먼저 임계 영역과 레이스 컨디션이 무엇인지 알아봅니다. 이후 레이스 컨디션이 발생하는 이유를 살펴보고 레이스 컨디션 관련 리눅스 커널 패치를 분석합니다.

임계영역(Critical Section)과 레이스 컨디션이란
임계 영역은 2개 이상 프로세스가 동시에 실행하면 동시 접근 문제를 일으킬 수 있는 코드 블록입니다. 1개 프로세스만이 실행해야 하는 특정 코드 블락의 시작과 끝 부분을 뜻합니다. 

만약 A 프로세스가 어떤 코드 구간을 실행하는 도중에 B프로세스가 같은 코드 블락을 실행한다고 가정하겠습니다. 이를 A 프로세스와 B 프로세스가 임계영역에 동시에 접근 중인 상황이라고 볼 수 있습니다. 이렇게 임계영역에 2개 이상 프로세스가 동시에 어떤 코드 연산을 수행하는 상황을 레이스 혹은 레이스 컨디션이라고 말합니다. 다른 컴퓨터 용어로 경쟁 조건이라고도 부릅니다.

기존 운영체제 도서에서 임계영역(Critical Section)이나 레이스 컨디션의 이해를 돕기 위해 화장실을 예를 많이 듭니다. 필자도 이 전통에 따르겠습니다.

위 그림은 한 사람이 들어갈 수 있는 공중 화장실을 A와 B란 사람이 들어가는 상황을 나타냅니다. 하나밖에 없는 화장실 문에 있는 자물쇠를 잠그고 용무를 보는 상황입니다. 그림에서 표시된 숫자는 화장실에 들어가기 전에 A와 B가 하는 동작을 의미합니다.

위 상황을 리눅스 커널 동기화 과정과 빗대서 생각해 봅시다.
 
첫 번째, 우리는 화장실에 들어가기 전에 화장실 문을 만지며 자물쇠가 잠겨 있나 확인합니다. 이미 다른 사람이 안에 있는지 살핍니다. 화장실 안에 사람이 없으면 화장실 문을 잠그면서 화장실에 들어갑니다. 

화장실 잠금장치는 여러 가지 종류가 있듯 리눅스 커널에도 스핀락, 뮤텍스 기법에 따라 자물쇠 잠금 방법이 다릅니다.

두 번째, 화장실에서 용무는 딱 한 사람만 볼 수 있습니다. 화장실에서 두 사람이 동시에 들어갈 수 없습니다. 유일하게 한 사람이 용무를 볼 수 있습니다. 이를 운영체제에서 임계영역(Critical Section)이라고 합니다.

세 번째, 화장실에 다른 사람이 용무를 보고 있으면 밖에서 기다립니다. 화장실에서 기다리는 방식은 사람이 따라 다릅니다. 용무가 급한 사람은 다른 일을 하지 않고 밖에서 발을 동동 구르며 계속 기다립니다. 어떤 이는 화장실 밖에서 잡지를 보면서 유유히 기다립니다.

리눅스 커널에서 스핀락의 경우 누군가 스핀락을 이미 획득했으면 화장실 밖에서 다른 일을 하지 않고 계속 기다립니다. 이를 Busy-wait라고 말합니다. 대신 뮤텍스는 자신을 대기열에 추가하고 화장실 밖에서 잠듭니다.

위에서 설명한 화장실에 서로 모르는 두 명의 사람이 같이 들어가게 되면 어떤 상황이 벌어질까요? 난처한 상황이 벌어집니다. 

이렇게 화장실에서 한 사람 만이 들어가 용무를 봐야 하듯 한 개 프로세스가 특정 코드 구간을 실행해야 할 경우가 있습니다. 이것을 임계영역이라고 합니다. 위 그림에서 화살표로 표시된 순간이 임계영역이며 다음과 같이 설명할 수 있겠습니다.

     “화장실에서 한 사람 만이 들어가 용무를 봐야 한다.”
      “특정 코드 구간을 한 개 프로세스만이 실행해야 한다.”

임계 영역을 위와 같이 정리할 수 있겠습니다. 이렇게 임계 영역에 두 사람(프로세스)가 동시에 접근하면 예상치 않은 문제가 발생할 수 있습니다.  
이번에는 레이스(Race)에 대해 알아봅시다. 
위 그림에서 A란 사람이 용무를 보기 전에 어떤 일인지 화장실 문에 있는 자물쇠를 제대로 잠그지 않았습니다. 이후 B라는 사람은 화장실 문이 잠겨 있지 않으니 화장실 안에 사람이 없다고 판단하고 문을 엽니다. 결국 화장실에 두 사람이 같이 들어가게 됩니다. 이런 상황을 레이스가 발생했다고 말할 수 있습니다. 

화장실에 2명의 사람이 같이 들어가듯 임계 영역에 두 개 프로세스가 동시에 접근하는 상황을 레이스라고 말합니다. 이런 조건을 레이스 컨디션(Race Condition)이라 합니다.

    “화장실에 두 명의 사람이 동시에 들어가 있다.”
   “특정 코드 구간에 2개의 프로세스가 실행된다.”

그렇다면 이 조건에서 레이스 컨디션은 다음과 같이 말할 수 있습니다.

    “A가 화장실 문을 제대로 잠그지 않았다.”
   “프로세스가 특정 코드 구간에 락(잠금)을 걸지 않았다.”

이렇게 화장실에 2명의 사람이 들어가는 불상사를 막기 위해서는 어떻게 해야 할까요? 화장실 자물쇠를 잘 잠가야 합니다. 커널에서도 마찬가지입니다. 임계 영역에서 하나의 프로세스만 실행해 레이스 컨디션이 발생하지 않게 적절히 락을 걸어줘야 합니다. 

이제 임계 영역과 레이스 컨디션에 대해 알아봤으니 커널 동기화에 대한 정의를 내릴 차례가 됐습니다.

   "레이스 컨디션을 방지하기 위한 위한 함수 호출과 설계 기법을 커널 동기화라고 한다."

리눅스 커널 실행 도중 위와 같이 레이스가 발생하면 보통 커널 크래시로 시스템 동작을 멈춥니다.

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

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

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



핑백

덧글

댓글 입력 영역