[Tip] semop() 세마포어 값을 변경

 

--------------------------------------------------------------------------------------------------------------------------

설명

--------------------------------------------------------------------------------------------------------------------------

semop() 함수는 세마포어의 값을 변경합니다. 세마포어를 사용하기 위해서는 

먼저 세마포어 값을 1 감소시키고, 사용 후에는 1 증가시키는데, 이렇게 세마포어값을 증감하는 것을 요청하는 함수입니다.

 

--------------------------------------------------------------------------------------------------------------------------

헤더

--------------------------------------------------------------------------------------------------------------------------

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

 

--------------------------------------------------------------------------------------------------------------------------

형태

--------------------------------------------------------------------------------------------------------------------------

int semop ( int semid, struct sembuf *sops, unsigned nsops )

 

--------------------------------------------------------------------------------------------------------------------------

인수

--------------------------------------------------------------------------------------------------------------------------

int semid 시스템에서 세머포어를 식별하는 집합 번호

struct sembuf *sops

세마포어 값을 계사하기위한 설정 값

struct sembuf {

    short sem_num;   세마포어 번호

    short sem_op;     세마포어 증감값

    short sem_flg;     옵션

}

 

sem_flg sem_flg 내용

IPC_NOWAIT

호출 즉시 실행하지 못했을 경우 기다리지 않고 실패로 바로 복귀합니다.

 

SEM_UNDO 프로세스가 종료되면 시스템에서 세마포어 설저을 원래 상태로 되돌립니다. 그러므로 보통 이 옵션을 사용합니다.

unsigned nsops

변경하려는 세마포어 개수로 변경하려는 세마포어 개수가 여러 개일 때 사용합니다.

예를 들어 변경하려는 세마포어 개수가 한 개라면

 

struct sembuf sbuf = { 0, -1, 0};

semop( semmop, &sbuf, 1);

 

이렇게 값이 1이 되지만 한번에 2개 이상의 세마포어를 변경한다면,

 

struct sembuf pbuf[2]   = {

      { 0,  1, 0} ,   // 첫번째 세마포어 값을 1 증가

      { 1, -1, 0}     // 두번째 세마포어 값을 1 감소

    }

semop( semmop, pbuf, 2);

 

--------------------------------------------------------------------------------------------------------------------------

반환

--------------------------------------------------------------------------------------------------------------------------

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 main.c -lpthread       // 소스에 쓰레드를 이용하므로 옵션에 -lpthread를 추가

]$ ./a.out

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 완전 종료

프로그램 종료

]$

+ Recent posts