세마포어_(시스템 프로그래밍)

김은혜·2024년 12월 4일
0

세마포어란?

: 여러 프로그램이 동시에 공유 자원에 접근하려고 할 때, 순서를 정해서 문제를 막아주는 도구

한 번에 한 명씩 들어갈 수 있도록 문 앞에 걸어두는 열쇠 같은 역할

왜 필요할까?

예를 들어, 집에 컴퓨터 한 대만 있다고 가정할 때, 가족 모두가 컴퓨터를 동시에 쓰려고 하면 문제가 생긴다.

  • 상황1: 동생은 컴퓨터를 켜서 게임을 하려고 한다.
  • 상황2: 나는 숙제를 하기 위해 컴퓨터를 끄려고 한다.
    위 상황 2개가 동시에 진행된다면 컴퓨터가 오작동할 수 있다.

    따라서 세마포어는 이런 상황에서 컴퓨터는 한 번에 한 명만 사용하도록 규칙을 세우고, 누가 사용할지 순서를 정해주는 역할을 한다.

어떻게 작동할까?

- p()함수 (잠금)

: 세마포어 값을 감소시켜 다른 프로세스의 접근 차단한다.

- v()함수 (해제)

: 세마포어 값을 증가시켜 대기 중인 프로세스가 접근 가능하도록 한다.

세마포어 함수

1. semget()

  • 세마포어 생성
  • 인자
    • key: IPC_PRIVATE 또는 ftok() 함수로 생성한 키
    • nsems: 생성할 세마포어 개수
    • semflg: 플래그 및 접근 속성
  • 반환값: 성공 시 식별자, 실패 시 -1

2. semctl()

  • 세마포어 제어
  • 인자
    • semid: 세마포어 식별자
    • semnum: 제어 대상 세마포어 번호
    • cmd: 수행할 명령
    • 추가 인자: 제어 명령에 따라 필요 시
  • 반환값: 성공 시 0, 실패 시 -1

3. semop()

  • 세마포어 연산 (잠금/해제)
  • 인자
    • semid: 세마포어 식별자
    • sops: sembuf 구조체의 주소
    • nsops: sops가 가르키는 구조체의 크기
  • 반환값: 성공 시 0, 실패 시 -1

세마포어 예제

#include <sys/ipc.h> // IPC 시스템 호출 함수
#include <sys/sem.h> // 세마포어 관련 함수
#include <sys/types.h> // 시스템 데이터 타입 정의
#include <errno.h> // 오류 코드
#include <unistd.h> // 시스템 호출 함수
#include <stdlib.h> // 표준 라이브러리 함수
#include <stdio.h> // 입출력 함수

// 세마포어 관련 유니언 정의
union semun {
	int val; // 세마포어 값
    struct semid_ds *buf; // 세마포어 상태 정보
    unsigned short *array; // 세마포어 값 배열
};

// 1)세마포어 생성 및 초기화 함수
int initsem(key_t semkey)
{
	union semun semunarg;
	int status = 0, semid;
	// 세마포어 생성 (IPC_CREAT | IPC_EXCL | 0600 : 생성 전 존재 여부 확인)
	semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0600);
	if (semid == -1)
	{
		// 세마포어가 이미 존재하는 경우
		if (errno == EEXIST)
		semid = semget(semkey, 1, 0); // 기존 세마포어 ID 가져오기
	}
	else
	{
		// 세마포어 초기화 (val = 1)
		semunarg.val = 1;
		status = semctl(semid, 0, SETVAL, semunarg); // 세마포어 값을 1로 설정
	}
	if (semid == -1 || status == -1)
	{
		perror("initsem");
		return (-1); // 오류 발생 시 -1 반환
	}
    
	return semid; // 세마포어 ID 반환
}

// 2)세마포어 연산: 세마포어 락 (잠금) 함수
int semlock(int semid)
{
	struct sembuf buf;
    
	buf.sem_num = 0; // 첫 번째 세마포어 사용
	buf.sem_op = -1; // 세마포어 값을 감소 (잠금)
	buf.sem_flg = SEM_UNDO; // 프로세스 종료 시 세마포어 원복
	if (semop(semid, &buf, 1) == -1)
	{
      perror("semlock failed");
      exit(1); // 오류 발생 시 종료
	}
    
	return 0;
}

// 2)세마포어 연산: 세마포어 언락 (잠금 해제) 함수
int semunlock(int semid)
{
  struct sembuf buf;
  
  buf.sem_num = 0; // 첫 번째 세마포어 사용
  buf.sem_op = 1; // 세마포어 값을 증가 (잠금 해제)
  buf.sem_flg = SEM_UNDO;
  if (semop(semid, &buf, 1) == -1)
  {
  	perror("semunlock failed");
  	exit(1); // 오류 발생 시 종료
  }
  
  return 0;
}

// 3) 세마포어 호출: 세마포어 처리 함수 (각 프로세스에서 호출)
void semhandle()
{
	int semid;
	pid_t pid = getpid(); // 현재 프로세스 ID 가져오기
    
	semid = initsem(1); // 세마포어 생성 또는 연결
	if (semid < 0)
	{
		exit(1); // 세마포어 초기화 실패 시 종료
	}
    
	// 세마포어 잠금 (크리티컬 섹션 시작)
	semlock(semid);

	printf("Lock : Process %d\n", (int)pid);
	printf("** Lock Mode : Critical Section\n");
	sleep(1); // 크리티컬 섹션에서 1초 동안 작업 수행
	printf("Unlock : Process %d\n", (int)pid);
    
	// 세마포어 잠금 해제 (크리티컬 섹션 끝)
	semunlock(semid);
    
	exit(0); // 프로세스 종료
}

// 4) 메인 코드
int main()
{
	int a;
	// 3개의 자식 프로세스 생성
	for (a = 0; a < 3; a++)
	{
		if (fork() == 0) // 자식 프로세스가 생성되면
		semhandle(); // 세마포어 처리 함수 호출
	}
    
	return 0;
}

실행화면

Lock : Process 1234
** Lock Mode : Critical Section
Unlock : Process 1234
Lock : Process 1235
** Lock Mode : Critical Section
Unlock : Process 1235
Lock : Process 1236
** Lock Mode : Critical Section
Unlock : Process 1236
  • 위 코드는 세마포어를 사용하여 여러 프로세스가 동시에 공유 자원에 접근하지 못하도록 순서를 정해주는 예제

주요 흐름

1.세마포어 초기화

  • semget() 함수를 사용하여 세마포어를 생성한다.
  • 세마포어 값은 1로 설정되어, 한 번에 하나의 프로세스만 크리티컬 섹션에 접근할 수 있도록 한다.
  1. 세마포어 잠금
  • semop() 함수로 세마포어 값을 -1로 변경하여 잠금을 설정한다.
  • 이를 통해 다른 프로세스가 크리티컬 섹션에 접근하지 못하게 한다.
  1. 세마포어 잠금 해제
  • 작업이 끝나면 semop() 함수로 세마포어 값을 1로 변경하여 잠금을 해제합니다.
  • 이렇게 하면 대기 중인 다른 프로세스가 크리티컬 섹션에 들어갈 수 있게 된다.
  1. 프로세스 생성
  • fork() 함수로 3개의 자식 프로세스를 생성한다.
  • 각 자식 프로세스는 semhandle() 함수를 호출하여 세마포어를 통해 순서대로 크리티컬 섹션에 접근한다.

결과

  • 각 프로세스는 세마포어를 이용해 순서대로 "크리티컬 섹션"에 접근하고, 1초 동안 작업을 수행한 뒤 순차적으로 잠금을 해제한다.
  • 세마포어 덕분에 여러 프로세스가 동시에 자원을 사용하지 않게 되어, 자원에 대한 충돌이 발생하지 않는다.

0개의 댓글

관련 채용 정보