세마포어 Semaphore

2019. 7. 25. 23:30임베디드/리눅스시스템프로그래밍

https://www.vectorstock.com/royalty-free-vector/semaphore-alphabet-flags-on-a-white-background-vector-5177923

 

세마포어란 깃발을 이용한 신호체계로, 뮤텍스와 같이 임계 영역을 보호하기 위한 수단이다

 

1. Counting Semaphore

- 세마포어의 초기값을 n으로 설정

- n번째 프로세스까지는 대기 없이 접근이 가능

- (n+1)번째 프로세스부터는 자원이 가능할 때까지 blocking 되어진다

- semaphore를 획득한 프로세스가 release 하면 기다리던 프로세스가 깨어나서 semaphore를 획득한다

 

2. Binary Semaphore

- 초기값을 1로 설정한 Counting Semaphore와 같으며, 곧 Mutex와 같다

 

POSIX Semaphore(unnamed)

1. sem_init

int sem_init(sem_t *sem, int pshared, unsigned int value)

pshared 0 : thread 간 공유

pshared 1 : process 간 공유

value는 semaphore의 초기값을 의미한다

 

2. sem_destory

다른 프로세스 혹은 스레드가 blocking 중인 semaphore의 destroy는 주의해야 한다

 

POSIX Semaphore(named)

1. sem_open

sem_t *sem_open(const char *name, int oflag,
                mode_t mode, unsigned int value);

name에는 경로를 기입하고, oflag는 보통 O_CREAT를 넣게 된다

mode는 기본 0644, 마지막 value에는 1을 넣으면 binary 그 이상은 counting으로 동작하게 된다

 

그리고 공통적으로 blocking 함수인 sem_wait로 세마포어를 취득하고, sem_post로 세마포어를 반납하게 된다

 

아래 예제는 counting semaphore로 생성한 후 show/wait/trywait/timedwait/release을 선택할 수 있다

깃허브주소: https://github.com/surinoel/linux/blob/master/ipc/sem_posix_named.c

 

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#define SEM_ID "/test_sem_id"
static void print_usage(char *progname)
{
printf("usage : %s (show|wait|trywait|timedwait|release)\n",
progname);
return;
}
static sem_t *init_semaphore(void)
{
sem_t *sem;
sem = sem_open(SEM_ID, O_CREAT, 0644, 3);
if(sem == SEM_FAILED) {
perror("sem_open()");
return NULL;
}
return sem;
}
static int sem_posix_show(sem_t *sem)
{
int i;
if(sem_getvalue(sem, &i) == -1) {
perror("sem_getvalue()");
return -1;
}
printf("semaphore : %d\n", i);
return 0;
}
static int sem_posix_wait(sem_t *sem)
{
return sem_wait(sem);
}
static int sem_posix_trywait(sem_t *sem)
{
return sem_trywait(sem);
}
static int sem_posix_timedwait(sem_t *sem)
{
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 3;
return sem_timedwait(sem, &ts);
}
static int sem_posix_release(sem_t *sem)
{
return sem_post(sem);
}
int main(int argc, char **argv)
{
int ret;
sem_t *sem;
if(argc < 2) {
print_usage(argv[0]);
return -1;
}
sem = init_semaphore();
if(sem == NULL) {
perror("init semaphore");
return -1;
}
if(!strcmp(argv[1], "show")) {
ret = sem_posix_show(sem);
} else if(!strcmp(argv[1], "wait")) {
ret = sem_posix_wait(sem);
} else if(!strcmp(argv[1], "trywait")) {
ret = sem_posix_trywait(sem);
} else if(!strcmp(argv[1], "timedwait")) {
ret = sem_posix_timedwait(sem);
} else if(!strcmp(argv[1], "release")) {
ret = sem_posix_release(sem);
} else {
print_usage(argv[0]);
return -1;
}
return ret;
}

 

'임베디드 > 리눅스시스템프로그래밍' 카테고리의 다른 글

쉘 스크립트 프로그래밍 - 1  (0) 2019.10.04
detach를 통한 스레드 반환  (0) 2019.07.26
sigprocmask oldset  (0) 2019.07.24
alarm과 sleep  (0) 2019.07.24
wait와 waitpid  (0) 2019.07.23