// 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 |