Time does not change us. It just unfolds us.

Etc

[IPC]Semaphore C 예제

소젬 2021. 10. 22. 14:26
// 2021-04-07 kimso
 
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <unistd.h>
 
/* 세마포어 공용체 정의 */
union semun{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
};
 
/* 세마포어를 생성하고 초기화 */
int initsem(key_t semkey){
    printf("***initsem function ! \n");
    union semun semunarg;
    int status = 0, semid;
 
    /*  인자로 받은 키를 지정해 세마포어 식별자 생성,
        return 값이 -1이고, errno 값이 EEXIST면 이미 존재하는 세마포어 식별자로
        기존 식별자 읽어옴 */
    semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | 0600);
 
    printf("semkey : %d, semid : %d\n", (int)semkey, semid);
 
    if(semid == -1) {
        if(errno == EEXIST) semid = semget(semkey, 1, 0);
    } else {
        /*semctl 함수를 통해 세마포어 값 1로 초기화 */
        semunarg.val = 1;
        status = semctl(semid, 0, SETVAL, semunarg);
        printf("status : %d\n", status);
    }
 
    if(semid == -1 || status == -1){
        perror("initsem");
        return(-1);
    }
 
    return semid;
}
 
/*  semlock 함수는 sem_op 값을 -1로 설정해 공유 자원을 얻고 잠금 기능 수행
    세마포어 값의 초깃값은 1로 설정했으므로, 처음 semlock 함수를 실행하는 프로세스는
    세마포어 값에서 1을 빼면 0이 되어 잠금 기능 수행 */
int semlock(int semid){
    printf("***semlock function ! \n");
    struct sembuf buf;
 
    buf.sem_num = 0;    //세마포어 번호
    buf.sem_op = -1;    //세마포어 연산
    /* (음수면 잠금 기능 수행 - 공유 자원 사용하려는 것
        양수면 세마포어 잠금 해제 후 사용 중이던 공유 자원 돌려줌*/
     
    /*sem_flg 설정을 통해 문제 발생 시 동작 취소 가능*/
    buf.sem_flg = SEM_UNDO; //연산을 위한 플래그 IPC_NOWAIT 또는 SEM_UNDO(프로세스 비정상적 종료)값
    if(semop(semid, &buf, 1) == -1){
        perror("semlock failed");
        exit(1);
    }
    return 0;
}
 
/*  sem_op 값을 1로 설정하여 사용 중인 공유 자원의 잠금 기능을 해제하고 되돌려줌.
    처음 semunlock함수 호출 시 세마포어 값이 0 이므로 1을 더하면 양수가 되어 잠금 해제. */
int semunlock(int semid){
    printf("***semunlock function ! \n");
    struct sembuf buf;
 
    buf.sem_num = 0;
    buf.sem_op = 1;
 
    /* sem_flg 설정으로 문제 발생 시 취소 가능 */
    buf.sem_flg = SEM_UNDO;
    if(semop(semid, &buf, 1) == -1){
        perror("semunlock failed");
        exit(1);
    }
 
    return 0;
}
 
/* 세마포어를 생성하여 잠금을 수행하고 작업 후 다시 잠금 해제*/
void semhandle(){
    printf("\n***semhandle function ! \n");
    int semid;
    pid_t pid = getpid();
 
    if((semid = initsem(1)) < 0) exit(1);
 
    semlock(semid);
 
    /* 처리문 삽입 가능 */
    printf("Lock : Process %d\n", (int)pid);
    printf("** Lock Mode : Critical Section\n");
    sleep(1);
    printf("Unlock : Process %d\n", (int)pid);
 
    semunlock(semid);
 
    exit(0);
}
 
/*  main함수에서는 fork함수를 세 번 호출해 자식 프로세스 세 개를 생성하고
    각 자식 프로세스는 semhandle함수 실행. 즉, 자식 프로세스가 모두 semhandle 함수 실행*/
int main(void){
    for(int i=0; i < 3; i++){
        if(fork() == 0) semhandle();
    }
 
    return 0;
}
시

실행화면

확인 후 삭제

 

'Etc' 카테고리의 다른 글

Database 용어 정리  (0) 2021.11.17
[IPC]Shared Memory 응용  (0) 2021.10.22
[IPC]Shared Memory  (0) 2021.10.22
[IPC]Semaphore  (0) 2021.10.22
[IPC]Semaphore 함수  (0) 2021.10.22