개요

세마포는 일반화된 뮤텍스라고 생각할 수 있다.

세마포어 S는 정수값을 가지는 변수이며, 다음과 같이 P와 V라는 원자적 명령에 의해서만 접근할 수 있다. (P와 V는 각각 try와 increment를 뜻하는 네덜란드어 Proberen과 Verhogen의 머릿글자를 딴 것이다.)

P는 임계 구역에 들어가기 전에 수행되고, V는 임계 구역에서 나올 때 수행된다. 이때 변수 값을 수정하는 연산은 모두 원자성을 만족해야 한다. 다시 말해, 한 프로세스(또는 스레드)에서 세마포어 값을 변경하는 동안 다른 프로세스가 동시에 이 값을 변경해서는 안 된다.

P연산은 S를 1감소시키고, S가 0과 같으면 Wait를 한다. V는 S를 1증가시키며, 만약 세마포S가 0에서 1로 바뀌면 기다리고 있는 P를 깨우게 된다.

세마포어는 두가지 중요한 방법으로 사용될 수 있다. Mutal Exclusion과 Signaling의 두가지 방법론이 있다. Mutual Exclusion은 Lock과 동이라하게 세마포를 1로 초기화 시켜서 사용하는 방법이며, Signaling은 초기화를 0으로 해준다음 다른 스레드가 up시키는 방법으로 사용한다.

semaphore.h

int sem_init(sem_t * semaphore_p, int shared, unsigned initial_val);

만일 pshared매개 변수가 '0'이 아닌 값을 가지고 있다면, 그 세마포어는 프로세스들 간에 공유할 수 있다. 만일 매개 변수 pshared이 '0' 이라면, 프로세스내의 스레드들간에 세마포어를 공유할 수 있다. 성공할 경우 sem_init() 함수는 ‘0’ 값을 반환한다. 그렇지 않을 경우 ‘-1’ 값을 반환하고 errno값을 설정하여 오류를 표시한다.

int sem_destroy(sem_t* semaphore_p);

세마포에 할당한 메모리 공간을 해제한다.

int sem_post(sem_t* semaphore_p);

세마포 값을 1 증가시킨다. V

int sem_wait(sem_t* semaphore_p);

세마포 값을 1 감소시킨다. P

예제

#include <stdio.h> 
#include <pthread.h> 
#include <semaphore.h> 
#include <unistd.h> 
  
sem_t mutex; 
  
void* thread(void* arg) 
{ 
    //wait 
    sem_wait(&mutex); 
    printf("\nEntered..\n"); 
  
    //critical section 
    sleep(4); 
      
    //signal 
    printf("\nJust Exiting...\n"); 
    sem_post(&mutex); 
} 
  
  
int main() 
{ 
    sem_init(&mutex, 0, 1); 
    pthread_t t1,t2; 
    pthread_create(&t1,NULL,thread,NULL); 
    sleep(2); 
    pthread_create(&t2,NULL,thread,NULL); 
    pthread_join(t1,NULL); 
    pthread_join(t2,NULL); 
    sem_destroy(&mutex); 
    return 0; 
}

참고

  1. http://neosrtos.com/docs/posix_api/semaphore.html