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

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