Semaphore(세마포어) 개념
- 프로세스간 메세지 전송을 하거나, 혹은 Shared Memory(공유메모리)를 통해서 특정 data를 공유하게 될경우
발생하는 문제는, 공유된 자원에 여러개의 프로세스가 동시에 접근을 하면서 발생한다.
단지 한번에 하나의 프로세스만 접근 가능하도록 만들어 줘야 하고,
이때 세마포어를 쓴다.
- 쓰레드에서는 뮤텍스, 프로세스에서는 세마포어
- 교착상태

A 프로세스가 k 에 접근하고 나오면 k = 2 라는 값을 예상할수 있다.
A 프로세스가 k 에 접근했을때, B 프로세스가 k 에 접근을 하고 일을 하고 나오면, k = 2 가 되고,
A 프로세스가 그후로 일을 하면 k = 3 이 된다.
즉, 예상한 값을 얻을수 없다.
이를 방지 하기 위해,
A 프로세스가 접근 했을때 다른 프로세스의 접근을 막고,
끝난후 접근을 풀어 준다.
이를 세마포어로 접근을 막고 접근을 허용 할수 있다.
- 차단을 원하는 자원에 대해서 semaphore를 생성하면 해당자원을 가리키는
semaphore 값이 할당 된다.
이 값이 0 이면 해당자원에 접근할수 없고,
0 보다 크면 해당자원에 접근할수 있다.

값이 0이면 자원을 사용할수 있을때까지 기다리고,
0보다 더 크면 자원에 접근해서 semaphore 값을 0 으로 감소 시켜서,
다른 프로세스가 자원에 접근 할수 없도록 하고,
자원의 사용이 끝나면 다시 semaphore 값을 증가 시켜 다른프로세스가 사용할수 있게 해준다.

#include <pthread.h></pthread.h>
#include <semaphore.h></semaphore.h>
#include <unistd.h></unistd.h>
#include <stdlib.h></stdlib.h>
sem_t bin_sem; //세마포어 생성
void *sem_rev(void *arg);
int state = 0;
pthread_t t1,t2,t3; //3개의 스레드 선언
char thread1[] = "Thread_A";
char thread2[] = "Thread_B";
char thread3[] = "Thread_C";
void * result_t = NULL;
* sem_init(sem_t *sem, int pshared, unsigned int value);
*
* sem가 가리키는 세마포어 객체를 초기화 한다.
* 아래 초기화문에서는 세번째 인자 1로 객체가 초기화 되며 두번째 인자 0은
* 세마포어가 현재 프로세스에서만 사용될지(현재 프로세스에서만 사용 = 0)
* 아니면 여러 프로세스간에 공유될지 지정한다.
* LinuxThreads는 세마포어가 여러 프로세스 간에 공유되는 것을 지원하지 않기때문에
* 두번째 인자가 0이 아닐 경우 sem_init 는 항상 ENOSYS 에러코드를 반환한다.
*/
if(state != 0) Error("sem_init Error\n");
pthread_create(&t2,NULL,sem_rev,thread2); //쓰레드 2 생성 (sam_rev 호출)
pthread_create(&t3,NULL,sem_rev,thread3); //스레드 3 생성 (sam_rev 호출)
pthread_join(t2,&result_t); //pthread_join 을 호출
pthread_join(t3,&result_t); //그 결과는 3개의 쓰레드 동작이 모두 종료되고 메인 프로세스가 종료된다.
* int sem_destroy(sem_t *sem);
*
* 세마포어와 이에 관련된 리소스들을 소멸시킨다.
*/
sem_destroy(&bin_sem);
}
int i = 0;
{
while(number != 0)
sleep(1);
printf("%s Running : %d\n",(char*)arg,number);
* int sem_post(sem_t *sem);
* 세마포어의 값을 하나 증가시킨다.
*/
sem_post(&bin_sem);
}
void *sem_rev(void *arg) {
int i = 0;
{
/*
* int sem_wait(sem_t *sem);
*
* 세마포어 값을 하나 감소시킨다
* 값이 0인 경우에는 1 이상이 될 때까지 대기 상태에 있다가
* 1이상이 되면 값을 감소시키며 대기상태에서 빠져나오게 된다.
* 즉 세마포어는 0보다 작은 값이 될 수 없다.
*/
sem_wait(&bin_sem);
number--;
printf("%s Running : %d\n",(char*)arg,number);
}
}
printf("%s\n",mes);
exit(0);
}
뮤텍스(Mutex)와 세마포어(Semaphore) 비교
사실 이 뮤텍스와 세마포어는 비슷하지만 차이가 있습니다.
뮤텍스 (Mutex)
스레드들 간에서 공유가 배제되는 객체입니다.
파일과 같은 공유 자원이 수행 중 오직 한 프로그램이나 스레이드에게만 소유되어야 할 필요가 있을 때
그 자원에 대한 뮤텍스 객체를 생성시킵니다.
뮤텍스가 비 신호 상태면 프로그램은 자원을 점유하여 사용한 후 이를 반환하고
다른 프로그램 또는 스레드가 자원을 사용중(뮤텍스가 신호 상태) 이면 대기 상태로 들어가 끝나기를 기다립니다.
뮤텍스는 여러 면에서 임계구역(Critical Section)과 비슷하고
대신 사용할 수도 있지만 이름을 가질 수 있다는 점에서 임계구역보다 우월한 점이 있습니다.
세마포어 (Semaphore)
운영 체계 또는 프로그램 작성 내에서 공유 자원에 대한 접속을 제어하기 위해 사용되는 신호입니다.
병행 내지 병렬로 동작되는 둘 이상의 프로세서 사이에서 마이크로프로세서
시간이나 입출력 접속구와 같은 공유 자원을 동시에 사용할 수 없기 때문에
한 프로세서가 사용하고 있는 동안에 세마포어를 세워서 다른 프로세서를 대기시키고
사용이 끝나면 해제시키는 방법으로 사용합니다.
이 둘을 비교/비유해 보면,
뮤텍스 : 화장실에 들어가기 위한 열쇠
세마포어 : 빈 화장실의 열쇠 개수
그러니까, 뮤텍스는 화장실에 들어갈 수 있는 열쇠를 한 명만 갖고 있다면!
한 번에 열쇠를 가진 한 명만이 화장실에 들어갈 수 있고 들어간 사람이 나와야만
기다리던 다음 사람이 열쇠를 받고 화장실에 들어갈 수 있습니다.
(여기서 기다리는 사람들은 대기 큐에 있는 프로세스가 되겠다)

반대로 세마포어는 들어갈 수 있는 화장실의 개수가 4개이고, 열쇠가 4개가 있다고 가정하면!
한 사람이 들어갈 때마다 들어갈 수 있는 화장실과 열쇠의 수는 1개씩 감소하게 되고
남은 열쇠가 없게 되면 다른 사람은 기다려야 하는 상황이지요.
화장실에 들어갔던 사람이 사용을 마치고 나오면 화장실과 열쇠의 사용 가능한 개수는
1개가 증가하고 다음 사람이 이용할 수 있게 되는 것!

즉, 결론을 말하자면 뮤텍스는 값이 1인 세마포어와 같습니다.














