Homework‎ > ‎

Synchronization by Semaphore

앞의 숙제(add1)의 Race Condition 문제를 Semaphore 를 이용하여 해결하는 방법

- Linux의 Advanced IPC 중 하나인 Semaphore 사용하여 Lock을 구현하여 사용한다.

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#define SEMPERM 0600
#define TRUE 1
#define FALSE 0
typedef union   _semun {
             int val;
             struct semid_ds *buf;
             ushort *array;
             } semun

int initsem (key_t semkey, int n)
{
   int status = 0, semid;
   if ((semid = semget (semkey, 1, SEMPERM | IPC_CREAT | IPC_EXCL)) == -1)
   {
       if (errno == EEXIST)
                semid = semget (semkey, 1, 0);
   }
   else
   {
       semun arg;
       arg.val = n;
       status = semctl(semid, 0, SETVAL, arg);
   }
   if (semid == -1 || status == -1)
   {
       perror("initsem failed");
       return (-1);
   }
   return (semid);
}

int p (int semid)
{
struct sembuf p_buf;
p_buf.sem_num = 0;
p_buf.sem_op = -1;
p_buf.sem_flg = SEM_UNDO;
if (semop(semid, &p_buf, 1) == -1)
{
perror ("p(semid) failed");
exit(1);
}
return (0);
}

int v (int semid)
{
struct sembuf v_buf;
v_buf.sem_num = 0;
v_buf.sem_op = 1;
v_buf.sem_flg = SEM_UNDO;
if (semop(semid, &v_buf, 1) == -1)
{
perror ("v(semid) failed");
exit(1);
}
return (0);
}

void main()
{
   key_t semkey = 0x200; // 서버에서 작업할 때는 자기 학번 등을 이용하여 다른 사람의 키와 중복되지 않게 해야 함
   int semid;
   pid_t pid;

   pid = getpid();
   if ((semid = initsem(semkey,1)) < 0)    // 세마포를 연결한다.(없으면 초기값을 1로 주면서 새로 만들어서 연결한다.)
      exit(1);
   // prinff("\nprocess %d before critical section\n", pid);
   p(semid);   // Lock Acquire()
   printf("process %d in critical section\n",pid);
    /* 화일에서 읽어서 1 더하기 */
   // printf("process %d leaving critical section\n", pid);
   v(semid);   // Lock Release()
   printf("process %d exiting\n",pid);
   exit(0);
}

Compile 하기
$
$ gcc -o add1 add1.c

Shell 에서 3개의 add1을 동시에  실행할 때
$
$ add1 &  add1 &  add1 &
Comments