본문 바로가기

운영체제

프로세스 동기화 문제

 흔하게 프로세스 동기화 문제는 임계구역을 문제로 하여 시작하게 된다. 각 프로세스에는 임계구역 내의 데이터 코드에서 다른 프로세스의 데이터와 접근할 수 있다. 이때, 발생할 수  있는 문제점으로는 하나의 프로세스가 자신의 임계구역에서 수행하는 동안엔 다른 프로세스가 접근할 수 없다는 것이다. 

 

 각 프로세스는 자신의 critical section에 진입 허가를 요청하게 된다. 이때, 요청을 구현하는 코드를 entry section이라고 부르며, 임계 구역 뒤에는 exit section이 있다. 이외의 코드 부분은 remainder section이라고 한다.

 

 임계구역 문제에 대한 해결책은 세 가지 요구 조건을 충족해야 한다.

1. 상호 배제 : 프로세스가 본인의 임계 구역 내에서 실행되고 있다면, 다른 프로세스들은 접근이 불가하다.

2. 진행 : 자신의 임계구역에서 실행되고 있는 프로세스가 없고, 그들 자신의 임계구역으로 진입하고자 하는 프로세스가 존재한다면, 나머지 구역에서 실행 중이지 않은 프로세스들만이. 임계구역의 선택권에 참가할 수 있다.

3. 한정된 대기 : 프로세스가 자기의 임계구역에 진입하려는 요청을 한 이후로, 그 요청이 허용될 때까지 다른 프로세스들이 자신의 임계구역에 진입이 허가되도록 허용되는 횟수가 정해져 있다. 

 

 단일 코어 환경에서는 인터럽트가 발생하는 것을 단순히 막는 것으로 문제를 해결할 수 있지만, 멀티 스레드 환경에서는 인터럽트를 비활성화하며 진입시키고자 하는 메시지를 블록하는 것이, 시스템 효율성을 떨어뜨린다.

 

 

 메모리 장벽 Memory Barriers

 

 컴퓨터 아키텍처가 응용 프로그램에게 제공하는 메모리 접근 시 보장되는 사항을 결정한 방식을 메모리 모델이라고 한다.

메모리 모델은 프로세스에 따라 상이하기 때문에 컴퓨터 아키텍처는 메모리의 변경 사항에 대하여 다른 프로세스에게 전달하는 명령어를 제공하는데, 이를 메모리 장벽이라고 불린다.

 시스템은 후속 적재 또는 저장 연산이 수행되기 전에 연산 및 저장이 완료되도록 한다. 

 

 

Mutex Locks

 

 임계구역 문제를 해결하기 위해서 개발된 도구가 mutex lock이다. 

프로세스는 임계구역에 들어가기 전에 반드시 락을 획득해야 하고 임계구역을 빠져나올 때 락을 반환해야 한다.

Mutex lock은 available boolean 타입의 변수를 가지는데, acquire() 함수 호출에 의해 관리된다.

 

acquire()
{
	while(!available)
    available = false;
    
    while(true)
    {
    	aquire lock
        critical section
        
        release lock
        remainder section
    }
}

 

 단점은 busy waiting을 해야한다. 프로세스의 임계구역에 접근을 시도하는 프로세스는 무한 대기를 하며 응답 요청을 기다려야한다. 이는, CPU 주기를 낭비함으로서 생산 효율성이 떨어진다.

 우리가 흔히 아는 mutex 락 유형에는 스핀락(spinlock)이다. 스핀락은 프로세스가 컨텍스트 스위칭이 필요하지 않으므로, 잠깐동안 락을 유지해야하는 경우 다른 스레드가 하나의 코어에서 임계구역을 실행하는 동안 스레드는 다른 코어에서 스핀을 할 수 있다.

 

 

세마포 Sepmaphores

 

 세마포 S는 정수 변수로, 초기화를 제외한 wait() 과 signal() 연산으로 접근이 가능하다.

한 스레드에서 세마포 값을 변경하면, 다른 어떤 스레드도 동시에 동일한 세마포 값을 변경할 수 없다. 

 

카운팅 세마포

카운팅 세마포는 제한 없는 도메인 값을 갖는다.

유한한 개수를 가진 자원에 대한 접근을 제어하는데 사요될 수 있다. 

이진 세마포

 0과 1 사이의 값만 가능하다. 

 

 

typedef struct{
	
    int value;
    struct process *lis

} semaphore;



wait(semaphore *S)
{
	S -> value--;
    if(S->value <0)
    {
    	add this process to S -> list;
        sleep();
    }
}

signal(semaphore *S)
{
	S-> value++;
    if(S->value <= 0){
    	remove a process Process from S ->list;
        wakeyup(Process);
    }
}

 

 sleep() 연산은 프로세스를 일시 중지시키며, wakeup(Process) 연산은 재개시킨다.

바쁜 대기를 하는 프로세스들의 리스트를 PCB에 있는 연결 필드에 의해 쉽게 구현될 수 있다. 

'운영체제' 카테고리의 다른 글

프로세스 간 통신  (0) 2024.12.11
스레드  (0) 2024.09.28
운영체제 구조  (0) 2024.09.14