운영체제 공룡책 공부하며 정리한 내용입니다.

Github : https://github.com/orgs/gochu-charmchi/discussions 정리보다는 머리에 넣고, 개념을 체화하는걸 중요하게 생각합니다. 그에 따라 정리가 이상할 수 있습니다.

협력적 프로세스

  • 시스템 내에서 실행 중인 다른 프로세스의 실행에 영향을 주거나, 영향을 받는 프로세스
  • 데이터 공유 방법
    • 논리 주소 공간(즉, 코드 및 데이터)을 직접 공유
    • 공유 메모리 또는 메시지 전달을 통해서만 데이터를 공유
  • 공유 데이터를 동시 접근하면, 데이터 일관성을 망칠 수 있음.
  • 질서 있는 실행을 보장하고, 데이터 일관성을 유지하는 방법

6.1 배경

  • 병행 또는 병렬로 실행 될 때 데이터의 무결성에 관해…
  • 한 쪽에서 count++ 하고, 다른 쪽에서 count—할 때, 결과를 보장할 수 없다.
  • 경쟁 상황
    • 동시에 여러 개의 프로세스가 동일한 자료에 접근하여 조작하고, 그 실행 결과가 접근이 발생한 특정 순서에 의존하는 상황

6.2 임계구역 문제

  • 임계구역
    • 하나 이상의 다른 프로세스와 공유하는 데이터에 접근 & 갱신하는 코드 부분
    • 동시에 두 프로세스는 그들의 임계구역에 들어갈 수 없다.
  • 진입 구역 - 임계 구역 - 퇴출 구역 / 나머지 구역
    • entry section - critical section - exit section / remainder section
  • 해결법
    • 상호 배제
      • mutual exclusion
      • 한 프로세스가 임계구역에서 실행될 때, 다른 프로세스들은 임계구역에서 실행될 수 없다.
    • 진행
      • progress
      • 자신의 임계구역에서 실행되는 프로세스가 없고, 자신의 임계구역으로 진입하려고 하는 프로세스들이 있다면, 나머지 구역에서 실행 중이지 않은 프로세스들만 다음에 누가 그 임계구역으로 진입할 수 있는지를 결정하는데 참여할 수 있다.
      • 이 선택은 무한정 연기될 수 없다.
    • 한정된 대기
      • bounded waiting
      • 프로세스가 자신의 임계구역에 진입하려는 요청을 한 후부터, 요청이 허용될 때까지 다른 프로세스들이 그들 자신의 임계구역에 진입하도록 허용되는 횟수에 한계가 있어야 한다.
  • 커널 코드는 경쟁 조건이 발생하기 쉽다.
  • 단일 코어 환경에서는 공유 변수 수정 중 인터럽트가 발생하지 않는다면, 선점 없이 순서대로 실행될 수 있다는 것을 확신할 수 있다.
  • 다중 프로세서 환경에서는 메시지(인터럽트 발생 중단)가 전달되는데 시간이 많이 걸릴 수 있어 불가능하다.
    • 시스템 효율성 감소, 임계구연 진입 지연 등의 문제가 생긴다.
  • 선점형 커널과 비선점형 커널 두 가지의 접근법이 사용된다.
    • 비선점형 커널은 커널 자료구조에 대한 경쟁 조건을 염려할 필요는 없다.
    • 선점형 커널에서는 신중하게 설계해야 한다.
      • SMP(symmetric multiprocessing)에서 더 어렵다
  • 선점형 커널이 민첩하기 때문에 선호된다.

6.3 Peterson의 해결안

  • 두 프로세스가 두 개의 데이터 항목을 공유하도록 하여 해결한다.
    • int turn, boolean flag[2];
  • turn이 궁극적인 값이 누가 임계구역에 진입할 것인지를 결정한다.
  • 상호 배제
    • flag[j] false or turn i 여야 한다.
    • turn 은 i이거나 j이다.
  • 진행 & 한정된 대기
    • 임계 구역을 flag[j] true && turn j 로 묶어두기
  • 최신 컴퓨터 아키텍처에서는 프로세서, 컴파일러가 작업을 재정렬 함
    • 종속성이 없는 읽기 및 쓰기 작업을 재정렬 함.

6.4 동기화를 위한 하드웨어 지원

메모리 장벽

  • 메모리 모델
    • 프로그램이 메모리에 접근할 때 그 접근 순서와 동작이 어떻게 보장되는지를 규정한 규칙
    • 강한 순서 : 한 프로세서의 메모리 변경 결과가 다른 모든 프로세서에 즉시 보임.
    • 약한 순서 : 한 프로세서의 메모리 변경 결과가 다른 프로세서에 즉시 보이지 않음.
  • 메모리 장벽 (메모리 펜스)
    • memory barriers, memory fences
    • 메모리의 모든 변경 사항을 다른 모든 프로세서로 전파하는 명령어
    • 실행될 때, 시스템은 후속 적재 또는 저장 연산이 수행되기 전에, 모든 적재 및 저장이 완료되도록 한다.
    • 상호 배제를 보장하는 특수 코드를 작성하는 커널 개발자만 사용한다.

하드웨어 명령어

  • 운영체제는 한 워드의 내용을 검사 & 변경, 두 워드의 내용을 swap할 수 있는 원자적 명령어를 제공한다.
  • test_and_set() 을 통해 간단히 상호 배제를 구현할 수 있다.
  • compare_and_swap() (CAS) 를 이용해 하나의 변수를 이용해서 상호배제 구현 가능
    • 한정된 대기를 만족시키지 못함
    • 모두(상호배제, 진행, 한정된 대기)를 충족하는 코드가 있음.
      • boolean waiting[n], int lock 을 이용.
      • p.296

원자적 변수

  • 기본 데이터 유형에 대한 원자적 연산을 제공한다.
  • 상호 배제를 보장하는데 사용될 수 있다.
    • 하지만 경쟁 조건을 완벽히 해결하지는 않는다.

6.5 Mutex Locks

  • 하드웨어 기반 해결책은 응용 프로그래머는 사용할 수가 없다.
  • MUTual EXclution mutex
  • 임계구역 보호, 경쟁 조건 방지
  • 임계구역 들어가기 전에 락 획득, 빠져나올 때 락 반환
    • 사용 불가 락을 획득하려고 하면, block된다.
  • acquire()release()는 원자적으로 수행되어야 한다.
    • CAS로 구현될 수 있다.
  • 바쁜 대기(busy wating)를 해야한다.
    • 다른 프로세스가 임계구역에 있는 동안 CPU에서 while을 호출하며, 문제가 된다.
      • CPU 낭비
  • busy waiting을 하는 락을 스핀락(spinlock)이라고도 한다.
    • 락을 사용할 수 있을 때까지, 프로세스가 회전하기 때문,
    • 문맥 교환이 필요하지 않다는 장점이 있다.
      • 락이 잠깐 걸리는 상황에서는 선호된다.

[! question] 스핀락의 장점과 단점은? 장점 : 문맥 교환이 필요하지 않다. 단점 : busy waiting을 하기 때문에, CPU 실행 시간이 낭비된다.

6.6 Semaphores

  • 정수 변수 S, 초기화를 제외하거는 원자적 연산인 wait(), signal()로 접근할 수 있다.
  • 세마포의 정수 값을 변경하는 연산은 원자적으로 수행되어야 한다.
    • wait(S)의 경우, S 정수 값 검사(S<=0) 작업과, 그에 따라 S-- 작업 인터럽트 되지 않고 실행되어야 한다.

세마포 사용법

  • Semaphore usage
  • counting
    • 카운팅 세마포의 값은 제한 없는 영역을 갖는다.
    • 유한한 개수의 자원에 대한 접근을 제어하는데 사용될 수 있다.
  • binary
    • 0과 1사이의 값만 가능하다.
    • mutex락과 유사하게 동작한다.

세마포 구현

  • busy waiting 이 아닌, 프로세스를 semaphore에 연관된 대기 큐에 넣고, 다른 프로세스가 signal() 하면 프로세스를 준비 완료 상태로 변경하고 준비 완료 큐 넣는다.
  • 세마포 음수 가능 음수일 때, 절댓값은 세마포를 대기하고 있는 프로세스들의 수
  • 세마포 리스트에 임의의 큐잉 전략을 사용할 수 있다.
    • FIFO로 한정된 대기를 구현할 수 있다.
  • 세마포는 원자적으로 실행되어야 한다
    • 단일 처리기 환경에서는 인터럽트를 금지함으로써 해결할 수 있다.
    • 다중 처리기 환경에서는 모든 처리 코어에서 인터럽트를 금지하여야만 한다.
      • CAS 또는 스핀락을 제공하여야 한다.
  • 바쁜 대기는 극도로 비효율적이다.

6.7 모니터

  • mutex 혹은 세마포를 사용할 때에도 그러한 오류는 일어날 수 있다.
    • 프로그램의 세마포에 대한 wait, signal의 연산의 순서가 뒤바뀔 경우
      • 여러 프로세스가 임계구역 안에서 실행될 수 있다.
    • signal 써야할 곳에 wait를 쓴 경우.
      • 세마포를 사용할 수 없다.
    • 프로세스가 wait나 signal, 또는 둘 다 빠뜨릴 경우.
      • 상호 배제 위반 or 영원히 locking

모니터 사용법

  • 추상화된 데이터 형(ADT)
    • 데이터와 데이터 조작 함수들의 집합을 하나의 단위로 묶어 보호한다.
    • 함수의 구현은 ADT의 특정 구현과는 독립적이다.
  • 모니터 형
    • 모니터 내부에서 상호 배제가 보장되는 프로그래머가 정의한 일련의 연산자 집합
    • 변수들의 선언을 포함하고 있는데, 모니터 내에 정의된 함수만에 접근할 수 있다.
    • 모니터 안에 항상 하나의 프로세스만에 활성화되도록 보장해 준다.
  • condition
    • condition x; x.wait(), x.signal()

세마포를 이용한 모니터의 구현

  • mutex 라는 이진 세마포
    • wait(mutex), signal(mutex)
  • 모니터 구현 시, signal-and-wait 기법 사용
    • signaling 프로세스는 실행 재개되는 프로세스가 모니터를 떠나든지
      • wait 할 때까지 자신이 기다리던지
        • 자신이 기다리기 위해 next라는 이진 세마포 추가 필요.
  • 진짜 무슨 소리인지 모르겠어요

모니터 내에서 프로세스 수행 재개

  • 여러 프로세스가 대기 중일때, 어떤 프로세스가 수행 재개될 것인가
  • conditinal-wait
    • x.wait(c)
    • wait 연산이 호출 될 때, 값이 계산된다.
    • c의 값은 우선순위 번호
  • ResourceAllocator 모니터
    • 한 개의 자원을 여러 프로세스 사이에 할당해 준다.
    • 자원 할당 필요시, 자원 사용 최대 시간 설정
      • 가장 적은 시간을 희망한 프로세스에 자원 할당
    • 문제
      • 프로세스가 자원에 대한 허락 없이 액세스할 경우
      • 프로세스가 자원에 대한 허락 이후, 방출하지 않을 경우
      • 프로세스가 자원에 대한 허락 없이, 방출할 경우.
      • 프로세스가 자원에 대한 허락을 받은 다음, 방출없이, 또 요청할 경우
    • 해결 (둘 다 지켜져야 함)
      • 프로세스들이 정확한 순서에 맞추어 호출하는지 검사
      • 비협조적 프로세스가 액세스 제어 프로토콜 사용치 않아서 상호 배제 규칙 경우를 무시하여 공유 자원 직접 액세스 하지않는다는 것을 보장해야 한다.

6.8 라이브니스

  • 프로세스가 실행 수명주기 동안 “진행”되는 것을 보장하기 위해 시스템이 충족해야 하는 일련의 속성
  • 라이브니스 실패
    • 성능과 응답성이 나쁜 것이 특징

교착 상태

  • 두 개 이상의 프로세스들이 대기중인 프로세스들 중 하나에 의해서만 야기될 수 있는 이벤트를 기다리는 상황
    • 이벤트 : 자원의 획득과 방출

우선순위 역전

  • 높은 우선순위 프로세스가 낮은 우선순위 프로세스에 의해 접근되는 커널 데이터를 읽거나, 변경할 필요가 있을 때 어려움.
  • L < M < H
  • 해결책
    • 우선순위 상속 프로토콜
    • 우선순위가 높은 프로세스가 필요로 하는 자원을 사용하는 낮은 프로세스에게 높은 우선순위를 상속한다.

평가

  • CAS 기반 접근은 낙관적인 접근법
    • 변수를 갱신 충돌 감지 (갱신 중인지 확인) 갱신될 때까지 반복 시도
  • 상호 배재 락킹은 비관적 전략
    • 다른 스레드가 갱신 중이라고 가정하고 갱신 전에 비관적으로 락 획득
  • 평가
    • 경합 없음 : CAS 동기화 > 기존 동기화
    • 적당한 경합 : CAS 동기화 >> 기존 동기화
    • 심한 경합 : 기존 동기화 >> CAS 동기화
  • 원자적 정수
    • 기존 락보다 훨씬 가벼움
    • 일반 변수에 대한 단일 업데이트에서 적합
  • 스핀락
    • 락이 짧은 다중 처리기 시스템에서 적합
  • mutex
    • 세마포보다 간단, 오버헤드 적음
    • 임계구역에 대한 접근 보호에 적합
  • 세마포
    • 한정된 수의 자원에 대한 접근을 제어하는 것
  • reader-writer 락, mutex 락
    • reader-writer 락이 선호된다.
  • 모니터, 조건 변수
    • 고급 도구
    • 단순성, 사용 편의성
    • 상당한 오버헤드가 있을 수 있음.
    • 구현에 따라 심한 경합 상황에서 확장성 좋지 않을 가능성 높음
  • 연구
    • 더 좋은 코드 생성하는 컴파일러 설계
    • 병행 프로그래밍 지원 언어 개발
    • 기존 라이브러리 및 API의 성능 향상