한 번에 한 명씩 들어갈 수 있도록 문 앞에 걸어두는 열쇠 같은 역할
예를 들어, 집에 컴퓨터 한 대만 있다고 가정할 때, 가족 모두가 컴퓨터를 동시에 쓰려고 하면 문제가 생긴다.
따라서 세마포어는 이런 상황에서 컴퓨터는 한 번에 한 명만 사용하도록 규칙을 세우고, 누가 사용할지 순서를 정해주는 역할을 한다.
: 세마포어 값을 감소시켜 다른 프로세스의 접근 차단한다.
: 세마포어 값을 증가시켜 대기 중인 프로세스가 접근 가능하도록 한다.
#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.세마포어 초기화