본문 바로가기
시스템소프트웨어/실습

12) semaphore

by LaTale 2017. 6. 6.

세마포어를 이용한 동기화


세마포어 생성(semget)

1
2
3
4
5
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semget(key_t key, int num_sems, int sem_flags);

key_t key : 세마포어를 구별하기 위한 식별 번호

int num_sems : 세마포어는 배열로 이루어져 있는데 이 배열의 크기를 설정한다.

sem_flags : 세마포어의 생성방식

 - IPC_CREATE는 커널에 key값의 세마포어가 없다면 생성한다.

 - IPC_EXCL은 IPC_CREATE와 함께 사용하는데 key값의 세마포어가 이미 존재한다면 에러 값을 반환한다.

반환)

성공시 세마포어 식별자(0 이상의 정수)를 반환한다.

실패시 -1을 반환한다.


세마포어 연산(semop)

1
2
3
4
5
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);

int sem_id : 세마포어를 구별하기 위한 식별자

struct sembuf *sem_ops : sembuf 구조의 배열(구조체 배열) sembuf는 <sys/sem.h>에 정의되어 있다.

size_t num_sem_ops : sem_ops의 개수

sembuf 구조체에는 적어도 다음과 같은 멤버가 있다.

1
2
3
4
5
struct sembuf {
   short sem_num;
   short sem_op;
   short sem_flg;
}

sem_num : 연산을 수행할 세마포어 번호이며 0부터 전체 개수 -1의 값을 가진다. 배열이 아니라면 일반적으로 0을 가진다.

sem_op : 수행할 연산을 뜻한다. 3가지로 나뉜다.

 - 음수일 때 : 세마포어의 값(semval)이 충분히 크다면(뺄 수 있는 상태) sem_op만큼 감소시킨다. 아직 크지 않다면 충분히 커질 때까지 기다린다(sleep). 만일 충분히 크지 않은 상태에서 sem_flg가 IPC_NOWAIT라면 즉시 -1을 반환하고 errno값을 EAGAIN으로 한다.

 - 0일 때 : 세마포어의 값이 0이 될 때까지 기다린다. 만일 세마포어의 값이 아직 0이 아니고 sem_flg가 IPC_NOWAIT라면 즉시 오류 값을 돌려주게 된다.

 - 양수일 때 : 세마포어의 값을 sem_op만큼 증가시킨다. v()연산과 같다.

sem_flg : 연산을 위한 플래그.

 - IPC_NOWAIT : 바로 처리할 수 없는 상황이면 errno값을 EAGAIN으로 설정한다.

 - SEM_UNDO : 프로세스가 비정상적으로 갑자기 종료할 때 세마포어 동작을 취소한다.

반환)

성공시 0을 반환한다.

실패시 -1을 반환한다.


세마포어 제어(semctl)

1
2
3
4
5

#include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semctl(int sem_id, int sem_num, int command, ...);

int sem_id : 세마포어를 구별하기 위한 식별자

int sem_num : 제어할 세마포어 번호, 배열이 아니라면 일반적으로 0을 가진다.

int command : 제어 명령어값. 여러가지가 있지만 일반적으로 사용하는 두 가지만 적겠다.

 - SETVAL : 세마포어의 값을 semun공용체의 val로 설정(변경)한다.

 - IPC_RMID : semid로 지정한 세마포어와 관련된 데이터 구조체를 제거한다.

... : 제어 명령에 따라 필요시 사용할 세마포어의 공용체 주소이다. 사용시에는 적어도 다음과 같은 멤버를 가진다.

1
2
3
4
5

union semun { int val; struct semid_ds *buf; unsigned short *array; }

반환)

SETVAL, IPC_RMID 두 command 모두 성공시 0을 반환한다.

실패시 -1을 반환한다.





set_semvalue함수는 semctl()에서 SETVAL을 이용해 세마포어를 초기화한다.

del_semvalue함수는 semctl()에서 IPC_RMID를 이용해 세마포어를 제거한다.

semaphore_p함수는 세마포어를 -1씩 해준다.

semaphore_v함수는 세마포어를 +1씩 해준다.

위에 나온 함수들을 그대로 이용했기 때문에 어려운 소스는 아니다.

_M#]


'시스템소프트웨어 > 실습' 카테고리의 다른 글

14) named pipe, socket  (0) 2017.09.04
13) pipe  (0) 2017.08.31
11) shared memory  (0) 2017.06.01
10) thread attributes  (0) 2017.05.02
9) semaphore, mutexes  (0) 2017.04.06