------------------------------ 실전 예제~ ---------------------------------
pthread 가 들어있는 파일 컴파일시!
gcc -lpthread 파일명.c 하면 딘다.
직접 구현해보고자 해서 이것저것 검색하다가 쉬운 예제가 나왔다.
이 에제를 따라하면서 이해하면 위에서 공부한 이론이 한방에 이해갈 것이다.
퍼온 소스에 주석만 좀 자세히 달아보았다.
= 초기화 함수
int sem_init(sem_t *sem, int pshared, unsigned int value);
= 세마포어 값 감소 함수
int sem_wait(sem_t *sem);
= 세마포어 값 감소 함수인데 넌 블로킹이라서 0에서 대기하지 않고 바로 EAGAIN(error의 일종) 를 리턴
int sem_trywait(sem_t *sem);
= 세마포어 값 증가 함수
int sem_post(sem_t *sem);
= sval 이 가리키는 위치에 sem 세마포어의 현재값을 저장
int sem_getvalue(sem_t *sem, int *sval);
= 세마포어 객체 삭제(할당된 자원 해제)
int sem_destroy(sem_t *sem);
----------------- 반환값 -----------------------
sem_wait와 sem_getvalue 는 항상 0을 반환
다른 모든 세마포어 함수들은 성공시 0, 실패시 -1 반환
실패 반환시 errno변수에 해당 에러코드를 기록!
----------------- 에러 ------------------------
sem_init 함수 에러시 errno 변수에 설정된다.
EINVAL : value는 카운터의 최대값인 SEM_VALUE_MAX 값보다 크다
ENOSYS : pshared 값이 0이 아니다.
sem_trywait 함수 에러시 errno 변수에 설정된다.
EAGAIN : 현재 세마포어의 카운터 값이 0이다.
sem_post 함수 에러시 errno 변수에 설정된다.
ERANGE : 증가 후 세마포어의 값이 SEM_VALUE_MAX 값보다 커진다.
sem_destroy 함수 에러시 errno 변수에 설정된다.
다른 쓰레드가현재 해당 세마포어를 기다리는 중이다.
----------------- SOURCE -----------------------
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include<stdlib.h>
void Error(const char *mes);
int number = 0; //일반출력변수
sem_t bin_sem; //세마포어 생성
void *sem_snd(void *arg);
void *sem_rev(void *arg);
int main()
{
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 에러코드를 반환한다.
*/
state = sem_init(&bin_sem,0,0); //최초 으로 세팅
if(state != 0) Error("sem_init Error\n");
pthread_create(&t1,NULL,sem_snd,thread1); //쓰레드 1 생성 (sam_snd 호출)
pthread_create(&t2,NULL,sem_rev,thread2); //쓰레드 2 생성 (sam_rev 호출)
pthread_create(&t3,NULL,sem_rev,thread3); //스레드 3 생성 (sam_rev 호출)
pthread_join(t1,&result_t); //쓰레드가 종료되기를 기다린 후 메인 프로세스가 종료되도록
pthread_join(t2,&result_t); //pthread_join 을 호출
pthread_join(t3,&result_t); //그 결과는 3개의 쓰레드 동작이 모두 종료되고 메인 프로세스가 종료된다.
printf("Finale Number : %d\n",number);
/*
* int sem_destroy(sem_t *sem);
*
* 세마포어와 이에 관련된 리소스들을 소멸시킨다.
*/
sem_destroy(&bin_sem);
return 0;
}
void *sem_snd(void *arg)
{
int i = 0;
for(i=0; i<4; i++)
{
while(number != 0)
sleep(1);
number++;
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;
for(i=0; i<2; i++)
{
/*
* int sem_wait(sem_t *sem);
*
* 세마포어 값을 하나 감소시킨다
* 값이 0인 경우에는 1 이상이 될 때까지 대기 상태에 있다가
* 1이상이 되면 값을 감소시키며 대기상태에서 빠져나오게 된다.
* 즉 세마포어는 0보다 작은 값이 될 수 없다.
*/
sem_wait(&bin_sem);
number--;
printf("%s Running : %d\n",(char*)arg,number);
}
}
void Error(const char *mes)
{
printf("%s\n",mes);
exit(0);
}
'개발자 > Programming' 카테고리의 다른 글
OpenMP 멀티 쓰레드 구현, 시작 (0) | 2020.08.28 |
---|---|
비쥬얼 스튜디오 코드 필수 익스텐션 10개 추천 (0) | 2020.06.23 |
VS Code 편집기 분할 단축키 (0) | 2020.05.19 |
vscode에서 깃허브 연동 종결 (퍼옴) (0) | 2020.04.26 |
디자인 패턴 (전략 패턴) (0) | 2020.04.15 |