본문 바로가기
programming/Unix

[Unix Programming] 11. 세마포어

by je0nsye0n 2025. 1. 16.

세마포어

  • 세마포어란?

→ 멀티프로세싱 환경에서 공유자원의 접근을 제한하기 위한 대표적인 방법

p(sem) or wait(sem)
// critical section
v(sem) or signal(sem)
  • p(sem) or wait(sem)
// 세마포어의 wait 연산은 지나가느냐 or block 둘 중 하나임
if(sem > 0)
	decrement sem by one
else
	wait : sem이 non-zero가 될 때까지 (blocking)
	wait이 풀림 : then decrement
  • v(sem) or signal(sem)
increment sem by one

if(queue of waiting process not empty)
	restart first process in wait queue
  • OS의 세마포어와 유닉스의 세마포어 차이점
    • +1/-1 연산이 아니라 +n/+m 연산이 가능하다 (이는 1:n의 동기화가 가능함을 의미)
    • 음수가 없음 : 0 or 양의 정수만 갖기 때문에 기다리는 프로세스들은 빼지 않고 기다림
    • 0 연산이 있기 때문에 큐가 2개

 

semget 시스템 호출

int semget(key_t key, int nsems, int permflags);
  • return 값 : 세마포어 집합 id

ex) 세마포어 집합 예시

index = 0 1 2 3

semval = 2 4 1 3

다음과 같은 세마포어 집합을 쓴다면,

nsems는 4이며 각각의 인덱스에 따른 다른 sem value값을 가질 수 있다.

 

semctl 시스템 호출

int semctl(int semid, int sem_num, int command, union semun arg);
  • sem_num : 집합 내 특정 세마포어를 지정함
  • command :
    1. IPC_STAT : 상태 정보를 arg에 저장
    2. IPC_RMID : 세마포어 집합 삭제
  • arg 쓰기 위해 주의해야 할 점

→ arg는 저장할 공간의 포인터를 반드시 넘겨줘야 사용 가능함

struct semid_ds temp;

arg.buf = temp;

semctl(semid, 0, IPC_STAT, arg);

**** 추가적인 command ****

// 단일 세마포어에 영향을 미치는 기능

GETVAL : semval값 return
SETVAL : semval값을 arg에 있는 값으로 지정
GETPID : sempid값 return
GETNCNT
GETZCNT

// 세마포어 집합 전체에 영향을 미치는 기능
GETALL : 모든 semval값을 arg.array에 저장
SETALL : arg에 있는 값을 semval에 저장

 

struct union arg

  • 해당 구조체를 선언해두고, 셋 중 하나를 사용하면 된다. (사용 시, 가장 큰 자료형의 크기를 가져감)
union semun{
	int val; // 단일 세마포어일 경우 사용
	struct semid_ds *buf; // IPC를 사용해서 정보 알아볼 때 사용
	unsigned short *array; // 여러 세마포어를 동시에 초기화할 때 사용
}

 

semop 시스템 호출

int semop(int semid, struct sembuf *op_arrary, size_t num_ops);
  • op_array : 수행할 연산 지정
  • num_ops : op_array 내의 sembuf의 수 (여러 개의 세마포어에 대한 연산을 동시에 지정 할 수 있음)

 

struct sembuf

struct sembuf{
	unsigned short sem_num; // 세마포어 인덱스
	short sem_op; // 연산 위치에 대하여 연산할 값 (음수 or 양수)
	short sem_flg; // blocking으로 보통 0을 적음
}
  • sem_flg : 0(blocking) or IPC_NOWAIT(non-blocking)
  • sem_op
    1. 음수 :
      • semval ≥ |sem_op| : semval -= |sem_op|
      • else : “semval ≥ |sem_op|”가 될 때 까지 wait 후, 가능해지면 연산
    2. 0 : semval 값에 변화는 없으며, sem_op는 semval이 0이 될 때까지 waiting
    3. 양수 :
      • semval += sem_op