C언어 세마포어 제어 함수 semctl()

2020. 3. 16. 09:43 컴퓨터/프로그래밍

C함수 세마포어 제어 semctl()

semctl() 함수는 세마포어를 제어합니다.

  • 헤더: sys/types.h, sys/ipc.h, sys/sem.h
  • 형태: int semctl ( int semid, int semnum, int cmd, union semun arg)
  • 인수: int semid 시스템에서 세머포어를 식별하는 집합 번호
    int semnum 세마포어 집합 내에서의 세마포어 위치
    int cmd 제어 명령

    cmd 내용
    GETVAL 세마포어의 현재 값을 구한다.
    GETPID 세마포어에 가장 최근에 접근했던 프로세스의 프로세스 ID를 구한다.
    GETNCNT 세마포어 값이 증가하기를 기다리는 프로세스의 개수
    GETZCNT 세마포어 값이 0 이 되기를 기다리는 프로세스의 개수
    GETALL 세마포어 집합의 모든 세마포어 값을 구한다.
    SETVAL 세마포어 값을 설정
    SETALL 세마퍼어 집합의 모든 세마포어 값을 설정
    IPC_STAT 세마포어의 정보를 구한다.
    IPC_SET 세마포어의 소유권과 접근 허가를 설정
    IPC_RMID 세마포어 집합을 삭제

  • union semun arg CMD에 따라 달라지며, 설정 또는 값을 구하는 변수
    union semun{
       int                  val;
       struct   semid_ds   *buf;
       unsigned short int  *arrary;
    }
    
  • 반환: 0 <= 성공, -1 == 실패

 

예제

예제에서는 두개의 쓰레드를 만들어 첫번째 쓰레드는 카운터 값을 증가 시키고 두번째 쓰레드는 카운터를 화면에 출력합니다. 카운터가 5 이상의 값이 되면 두 개의 쓰레드는 모두 종료하고 프로그램이 종료되면서 세마포어를 삭제합니다.

#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int         cnt   = 0;
static int  semid;

void p()
{
   struct sembuf pbuf;

   pbuf.sem_num   = 0;
   pbuf.sem_op    = -1;
   pbuf.sem_flg   = SEM_UNDO;

   if ( -1 == semop(semid, &pbuf, 1))
      printf( "p()-semop() 실행 오류\n");
}

void v()
{
   struct sembuf vbuf;

   vbuf.sem_num   = 0;
   vbuf.sem_op    = 1;
   vbuf.sem_flg   = SEM_UNDO;

   if ( -1 == semop( semid, &vbuf, 1))
      printf( "v()-semop() 실행 오류\n");
}

void *fun_thread1(void *arg)
{
   while( 1)
   {
      p();
      printf( "thread1 실행\n");
      if ( 5 < cnt)
      {
         printf( "thread1 완전 종료\n");
         v();
         break;
      }
      else
      {
         cnt++;
         usleep( 100);
         printf( "thread1 완료\n");
      }
      v();
   }
   return NULL;
}

void *fun_thread2(void *arg)
{
   while( 1)
   {
      p();
      printf( "thread2 실행\n");
      if ( 5 < cnt)
      {
         printf( "thread2 완전 종료\n");
         v();
         break;
      }
      else
      {
         printf( "카운터= %d\n", cnt);
         usleep( 100);
         printf( "thread2 완료\n");
      }
      v();
   }

   return NULL;
}

int main(int argc, char *argv[])
{
   pthread_t thread1;
   pthread_t thread2;
   union semun{
      int                  val;
      struct   semid_ds   *buf;
      unsigned short int  *arrary;
   }  arg;

   if ( -1 == (semid = semget( IPC_PRIVATE, 1, IPC_CREAT ¦ 0666)))
   {
      printf( "semget() 실행 오류\n");
      return -1;
   }

   arg.val  =  1;                // 세마포어 값을 1로 설정
   if ( -1 == semctl(semid, 0, SETVAL, arg))
   {
      printf( "semctl()-SETVAL 실행 오류\n");
      return -1;
   }

   pthread_create(&thread1, NULL, fun_thread1, NULL);
   pthread_create(&thread2, NULL, fun_thread2, NULL);
   pthread_join( thread1, NULL);
   pthread_join( thread2, NULL);

   if ( -1 == semctl(semid, 0, IPC_RMID, arg))
   {
      printf( "semctl()-IPC_RMID 실행 오류\n");
      return -1;
   }
   printf( "프로그램 종료\n");
   return 0;
}

실행 결과

]$ gcc test.c -lpthread
]$ ./a.out
thread2 실행
카운터= 0
thread2 완료
thread1 실행
thread1 완료
thread2 실행
카운터= 1
thread2 완료
thread1 실행
thread1 완료
thread2 실행
카운터= 2
thread2 완료
thread1 실행
thread1 완료
thread2 실행
카운터= 3
thread2 완료
thread1 실행
thread1 완료
thread2 실행
카운터= 4
thread2 완료
thread1 실행
thread1 완료
thread2 실행
카운터= 5
thread2 완료
thread1 실행
thread1 완료
thread2 실행
thread2 완전 종료
thread1 실행
thread1 완전 종료
프로그램 종료
]$
이 댓글을 비밀 댓글로