커널 내에서의 동기화
이번에는 운영체제 커널 내부에서 어떻게 동기화가 이루어지는지 살펴보겠습니다. 커널은 여러 프로세스와 스레드가 공유하는 데이터 구조에 접근하기 때문에, 데이터의 일관성을 유지하는 동기화 메커니즘이 필수적입니다.
Windows의 동기화
Windows는 다중 스레드 커널이며, 시스템 환경에 따라 다른 동기화 방법을 사용합니다.
단일 프로세서 시스템: 전역 리소스(global resource)에 접근할 때는, 해당 리소스에 접근하는 다른 인터럽트 핸들러의 인터럽트를 일시적으로 마스크(mask)하여 보호합니다.
다중 프로세서 시스템: 짧은 코드 세그먼트를 보호하기 위해 **스핀락(spinlocks)**을 사용합니다. 스핀락을 보유한 스레드는 선점되지 않도록 하여 효율성을 높입니다.
커널 외부의 스레드 동기화를 위해서는 **디스패처 객체(dispatcher objects)**를 제공합니다. 이 객체들은 뮤텍스, 세마포어, 이벤트, 타이머 등을 포함하며, **'신호 상태(signaled state)'**와 **'비신호 상태(nonsignaled state)'**를 가집니다. 스레드는 디스패처 객체가 신호 상태가 될 때까지 기다리며, 이때 스레드의 상태는 '대기(waiting)'로 바뀝니다.
또한, **임계 구역 객체(critical-section object)**라는 사용자 모드 뮤텍스를 제공하여, 경쟁이 없을 경우 커널 개입 없이 락을 획득하고 해제할 수 있어 효율적입니다.
Linux의 동기화
Linux 커널은 버전 2.6부터 완전한 선점형(preemptive) 커널로 전환했습니다.
원자적 정수(atomic integer): 간단한 정수 변수를 효율적으로 업데이트해야 할 때는 락의 오버헤드 없이 원자적(atomic) 연산을 보장하는 원자적 정수를 사용합니다.
뮤텍스 락과 세마포어: 커널 내의 임계 구역을 보호하기 위해 뮤텍스 락과 세마포어를 사용합니다.
스핀락 처리:
단일 프로세서 시스템: 스핀락 대신 **커널 선점(kernel preemption)**을 비활성화하는 방식으로 상호 배제를 구현합니다.
다중 프로세서 시스템: 스핀락을 사용하되, 짧은 시간 동안만 보유하도록 설계합니다.
선점 방지 카운터:
preempt_count
라는 카운터를 사용해 현재 스레드가 락을 몇 개 보유하고 있는지 추적합니다. 이 값이 0보다 크면 커널 선점을 안전하게 막습니다.
Last updated