식사하는 철학자 문제

임채욱·2021년 1월 27일
1

c

목록 보기
1/1

42의 철학자 과제를 해결하기 위해 기반 지식을 정리하였다.

https://ko.wikipedia.org/wiki/%EC%8B%9D%EC%82%AC%ED%95%98%EB%8A%94_%EC%B2%A0%ED%95%99%EC%9E%90%EB%93%A4_%EB%AC%B8%EC%A0%9C

위의 링크와 같이 유명한 철학자 문제를 시뮬레이션하는 과제이다.

과제는 3가지의 유형을 해결하도록 제시한다.

  • 스레드와 뮤텍스를 이용한 철학자 시뮬레이션
  • 스레드와 세마포어를 이용한 철학자 시뮬레이션
  • 프로세스와 세마포어를 이용한 철학자 시뮬레이션

각각의 철학자는 포크를 하나씩 가지고 있으며 두 개의 포크를 집어야만 식사를 할 수 있다.

첫번째 유형은 포크를 각각의 철학자가 가지고 있다.

나머지 2가지의 유형은 식탁의 중앙에 포크를 두고 철학자가 각자 집어간다.

아래에 정리한 함수를 활용하여 식사, 잠자기, 생각과 같은 행동을 하는 철학자를 만들 수 있다.

usleep

  • 지정한 마이크로 초 동안 대기 상태가 된다.
  • 지정한 시간에서 약간의 오차가 생길수 있기 때문에 정확한 간격을 주기 위해서는 목표시간까지 반복적으로 usleep(100)을 실행하는 함수를 만들 필요가 있다.
#include <unistd.h>

int usleep(useconds_t microseconds);

gettimeofday

  • 현재 시간을 가져오고 시스템의 시간값을 설정한다.
  • 이 함수를 이용하여 경과 시간을 구할 수 있다.
#include <sys/time.h>

int gettimeofday(struct timeval *tv, struct timezone *tz);

struct timeval {
    time_t       tv_sec;   /* seconds since Jan. 1, 1970 */
    suseconds_t  tv_usec;  /* and microseconds */
};

gettimeofday(&startTime, NULL);
// 특정 작업 수행
sleep(1);
gettimeofday(&endTime, NULL);
diffTime = ( endTime.tv_sec - startTime.tv_sec ) + ( endTime.tv_usec - startTime.tv_usec );

pthread_create

  • 특정 함수를 수행하는 스레드를 생성
  • 1번째 인자는 생성된 스레드를 식별하기 위해 사용되는 식별자
  • 2번째 인자는 스레드 특성을 지정하기 위해서 사용(기본 특성은 NULL)
  • 3번째 인자는 실행 할 함수
  • 4번째 인자는 스레드 함수의 인자
#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

struct thread_info {    /* Used as argument to thread_start() */
  pthread_t thread_id;        /* ID returned by pthread_create() */
  int       thread_num;       /* Application-defined thread # */
  char     *argv_string;      /* From command-line argument */
};

struct thread_info tinfo;

int	th_result;

th_result = pthread_create(&(tinfo.thread_id), NULL, t_function, (void *)&tinfo);

pthread_detacth

  • main 쓰레드에서 pthread_create 를 이용해 생성된 쓰레드를 분리시킨다.
  • 이 함수는 식별번호가 th인 쓰레드를 detach 시키는데, detach 되었을경우 해당(detach 된) 쓰레드가 종료될경우 pthread_join 을 호출하지 않더라도 즉시 모든 자원이 해제(free) 된다.
#include <pthread.h>

int pthread_detach(pthread_t th);

pthread_join

  • 특정 스레드의 종료를 기다리는 함수
  • 1번째 인자는 기다릴 스레드 식별자
  • 2번째 인자는 스레드의 리턴값이 저장된다.
#include <pthread.h>

int pthread_join(pthread_t th, void **thread_return);

pthread_mutex_init

  • 뮤텍스는 여러 개의 스레드가 공유하는 데이터를 보호하기 위해 사용
  • 보호하고자 하는 데이타를 다루는 코드영역을 단지 한번에 하나의 쓰레드만 실행가능 하도록 보호
  • 1번째 인자로 주어지는 mutex 객체를 초기화
  • 2번째 인자인 attr을 이용하여 mutex 특성 지정(기본 특성은 NULL)
#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutex_attr *attr); 

pthread_mutex_t mutex_lock; // 전역 변수로 사용해야 다른 스레드 함수에서 접근 가능할 듯

void *t_function()
{
    pthread_mutex_lock(&mutex_lock);
    // critical section
    pthread_mutex_unlock(&mutex_lock);
}

pthread_mutex_init(&mutex_lock, NULL);

pthread_mutex_destory

  • mutex 제거를 위해 사용
  • 반드시 unlock 상태이어야 한다.
#include <pthread.h>

int pthread_mutex_destroy(pthread_mutex_t *mutex);

pthread_mutex_lock

  • critcal section 에 들어가기 위해서 mutex lock 을 요청한다.
  • 만약 이미 다른 쓰레드에서 mutex lock 를 얻어서 사용하고 있다면 다른 쓰레드에서 mutex lock(뮤텍스 잠금) 을 해제할때까지(사용할수 있을때까지) 블럭 된다.
#include <pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutex);

pthread_mutex_unlock

  • critical section 에서의 모든 작업을 마치고 mutex lock 을 돌려주기 위해서 사용
#include <pthread.h>

int pthread_mutex_unlock(pthread_mutex_t *mutex); 

sem_open

  • 1번째 인자는 생성 또는 접근하고자 하는 세마포어의 이름
  • 2번째 인자는 세마포어 생성시 플래그
    • O_CREAT
    • O_EXCL
  • 3번째 인자는 플래그를 O_CREAT로 설정하면 사용 가능
    • S_IRWXR: 그룹 접근
    • S_IRWXO: 타인 접근
    • S_IRWXU: 개인 접근
  • 4번째 인자는 세마포어 초기값
    • unlock된 세마포어의 수를 의미
    • SEM_VALUE_MAX를 초과 할 수 없다.
  • 이름 있는 세마포어는 항상 /dev/sem 경로에 생성된다:
    • 이름이 /로 시작하면 세마포어는 그 이름으로 지어진다.
    • 이름이 /로 시작하지 않으면, 세마포어는 그 이름으로 지어지되 현재 경로 아래에 만들어진다.
#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>

sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

set_t *sem;

sem = sem_open(SEM_NAME, O_CREAT, 0664, 1);
if (sem == SEM_FAILED)
  sem_unlink(SEM_NAME);

sem_close

  • 세마포어 free
#include <semaphore.h>

int sem_close(sem_t *sem);

sem_post

  • semaphore의 값을 1증가
#include <semaphore.h>

int sem_post(sem_t *sem);

sem_t sem;
sem_post(&sem);

sem_wait

  • semaphore의 값을 1감소
  • 만약 semaphore의 값이 0일 경우 semaphore의 값이 증가할때까지 blocking
#include <semaphore.h>

int sem_wait(sem_t *sem);
  • 참조 횟수가 0에 도달한 경우 semaphore를 시스템에서 제거
  • sem_close 혹은 exit 된 이후에 제거됨
#include <semaphore.h>

int sem_unlink(const char *name);
profile
성장을 추구하는 개발자입니다

0개의 댓글