세마포어로 락을 구현중입니다.

kdoll의 이미지

Sys V 세마포어로 락을 사용하고 있는데요

read / write lock구현은 했는데요..

문제는 write lock을 요청하는 넘이 read lock때문에

굶어죽는데 뾰족한 수가 없는지요

ㅡ,.ㅡ;;의 이미지

라면이라도 끓여주면되지 않나요?ㅡ,.ㅡ;

read를 대신굶기면 될듯합니다...


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

cdpark의 이미지

write_lock이 하나라도 있으면 read_lock에 참여하지 못하도록 하는 것 아닌가요? 어떻게 구현하셨기에..

sodomau의 이미지

cdpark wrote:
write_lock이 하나라도 있으면 read_lock에 참여하지 못하도록 하는 것 아닌가요? 어떻게 구현하셨기에..

한 녀석이 read lock(shared lock이란 소리죠?)을 얻은 상태에서 다른 녀석들이 read_lock 과 write_lock을 요구할 경우, read_lock이 계속 우선권을 얻고 들어가게 구현하셨다는 소리 같은데요. 실제로 이렇게 할 경우, write lock은 위에서 질문하신 것 처럼 starvation에 빠지게 되겠죠.
해결책은 지금 생각 나는 것은.. write_lock 을 요구한 넘에게 카운터 하나 달아서 카운터가 꽉 차면 read_lock을 요구하는 넘이 있어도 못 얻도록 한다던가.. 머 그럼 되지 않을까요? 그냥 지금 생각한 건데..;; 헐헐;;

ㅡ,.ㅡ;;의 이미지

sodomau wrote:
cdpark wrote:
write_lock이 하나라도 있으면 read_lock에 참여하지 못하도록 하는 것 아닌가요? 어떻게 구현하셨기에..

한 녀석이 read lock(shared lock이란 소리죠?)을 얻은 상태에서 다른 녀석들이 read_lock 과 write_lock을 요구할 경우, read_lock이 계속 우선권을 얻고 들어가게 구현하셨다는 소리 같은데요. 실제로 이렇게 할 경우, write lock은 위에서 질문하신 것 처럼 starvation에 빠지게 되겠죠.
해결책은 지금 생각 나는 것은.. write_lock 을 요구한 넘에게 카운터 하나 달아서 카운터가 꽉 차면 read_lock을 요구하는 넘이 있어도 못 얻도록 한다던가.. 머 그럼 되지 않을까요? 그냥 지금 생각한 건데..;; 헐헐;;


결국 write 가 굶어 죽기전에 read 를 굶기는 방식이군요..ㅎㅎ
아마도 질문자는 하나의공유메모리로 다중프로세스간통신을 하는모양입니다.
프로세스들이 항상 리스닝하고 있다면 비효율적이므로 새메지지가 있을때만 즉각적으로 읽어들이도록 구현하시면 되는데 구현이 조금 복잡해는면도 있습니다.


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

kdoll의 이미지

답변들 감사합니다.

근데 약간은 추상적이라 구현에 문제가 있네요..

통신을 하는것은 아니구요

통신용 세마포어는 작성이 되어 동작을 잘하고 있습니다.

공유메모리 풀을 만들어 사용을 하고 있습니다.

근데 이넘이 자료구조가 좀 복잡하게 되어 있어서.

일단 구현을 보시구 좀더 구체적인 변경방법을..^^;


/*******************************************************
* System V 세마포어를 이용한 READ LOCK/WRITE LOCK
* 현재 write lock 가 경쟁상태에서 굶는문제 있음--;
*******************************************************/

/* read/write락을 사용하는 함수에서의 변수들 초기화 여부 */
static char           _is_init_lock_op = 0;
static struct sembuf  _get_rlock_op     [2];  /* read 락  요청 */
static struct sembuf  _release_rlock_op [1];  /* read 락  해제 */
static struct sembuf  _get_wlock_op     [3];  /* write 락 요청 */
static struct sembuf  _release_wlock_op [1];  /* write 락 해제 */


/*
  데이타 통신용으로 사용하는 세마포어 lock
*/
static struct sembuf  _get_cli_lock_op      [3];  /* writer 락요청          */
static struct sembuf  _release_cli_lock_op  [2];  /* writer 락해제(데이타)  */
static struct sembuf  _release_cli_lock_op_n[1];  /* writer 락해제(NO데이타)*/
static struct sembuf  _get_svr_lock_op      [3];  /* reader 락요청          */
static struct sembuf  _release_svr_lock_op  [1];  /* reader 락해제(처리)    */
static struct sembuf  _release_svr_lock_op_n[2];  /* reader 락해제(NO처리)  */


/* READ / WRITE LOCK에 필요한 sembuf구조를 초기화( 않되어 있다면) */
static void _init_sem_v_lock_op()
{
  if( ! _is_init_lock_op )
  {
    /******************************
    * 읽기 쓰기 락 관련 OP셋팅
    * 0 Read 락
    * 0 Write 락
    ******************************/

    L_MEMSET(_get_rlock_op,     0, sizeof(_get_rlock_op));
    L_MEMSET(_release_rlock_op, 0, sizeof(_release_rlock_op));
    L_MEMSET(_get_wlock_op,     0, sizeof(_get_wlock_op));
    L_MEMSET(_release_wlock_op, 0, sizeof(_release_wlock_op));

    /*  읽기락 요청용
        Write 세마포어가 0이 될때까지 대기  0
        read  세마포어   1증가              1 */
    set_sem_buf( &_get_rlock_op[0], 1, 0, 0);
    set_sem_buf( &_get_rlock_op[1], 0, 1, SEM_UNDO);


    /* 읽기락 해제용
       read 세마포어 1 감소 */
    set_sem_buf( &_release_rlock_op[0], 0, -1, SEM_UNDO | IPC_NOWAIT);


    /*  쓰기락 요청용
        write 세마포어가 0이 될때까지 대기 0
        read  세마포어가 0이 될때까지 대기 1
        write 세마포어   1   증가         2 */
    set_sem_buf( &_get_wlock_op[0], 1, 0, 0);
    set_sem_buf( &_get_wlock_op[1], 0, 0, 0);
    set_sem_buf( &_get_wlock_op[2], 1, 1, SEM_UNDO);

    /* 쓰기락 해제용
       write 세마포어 1 감소 */
    set_sem_buf( &_release_wlock_op[0], 1, -1, SEM_UNDO | IPC_NOWAIT);


    /*******************************************
    * 클라이언트 / 서버형태의 데이타 IPC락형태
    * 두개의 세마포어를 사용한다
    * 0 자원 유무 세마포어
    * 1 프로세싱중 여부 세마포어
    *******************************************/
    L_MEMSET(_get_cli_lock_op,        0,  sizeof(_get_cli_lock_op));
    L_MEMSET(_release_cli_lock_op,    0,  sizeof(_get_cli_lock_op));
    L_MEMSET(_release_cli_lock_op_n,  0,  sizeof(_release_cli_lock_op_n));
    L_MEMSET(_get_svr_lock_op,        0,  sizeof(_get_svr_lock_op));
    L_MEMSET(_release_svr_lock_op,    0,  sizeof(_release_svr_lock_op));
    L_MEMSET(_release_svr_lock_op_n,  0,  sizeof(_release_svr_lock_op_n));


    /*  클라이언트 데이타 넣기 전 락 요청 
        자원이 0인지 검사 존재하는지 검사  0
        진행중인 프로세스가 0인지 검사     1
        진행중인 프로세스를 1로 올림       2
    */
    set_sem_buf( &_get_cli_lock_op[0], 0, 0, 0);
    set_sem_buf( &_get_cli_lock_op[1], 1, 0, 0);
    set_sem_buf( &_get_cli_lock_op[2], 1, 1, SEM_UNDO);


    /*
      클라이언트 데이타가를 넣고 난 이후 락 Release
      자원 카운트를 1증가시키고         0
      진행중인 프로세스를 -1 감소시킴   1
    */
    set_sem_buf( &_release_cli_lock_op[0], 0, 1, IPC_NOWAIT);
    set_sem_buf( &_release_cli_lock_op[1], 1, -1, SEM_UNDO | IPC_NOWAIT);


    /*
      클라이언트 데이타를 넣지 않고 락 Release
      진행중인 프로세스를 -1 감소시킴  0
    */
    set_sem_buf( &_release_cli_lock_op_n[0], 1, -1, SEM_UNDO | IPC_NOWAIT);



    /* 
      서버에서 데이타가 존재할때 읽어가기 위한 락 요청 
      자료가 존재하는지 확인후 -1 감소시킴   0
      프로세싱 카운트가 0인지 확인           1
      프로세싱 카운트   1 증가               2
    */
    set_sem_buf( &_get_svr_lock_op[0], 0, -1, 0);
    set_sem_buf( &_get_svr_lock_op[1], 1, 0, 0);
    set_sem_buf( &_get_svr_lock_op[2], 1, 1, SEM_UNDO);

    /*
      서버에서 데이타를 처리했을때를 위한 락 release
      프로세싱 카운트 -1 감소시킴         0
    */
    set_sem_buf(&_release_svr_lock_op[0], 1, -1, SEM_UNDO | IPC_NOWAIT);


    /*
      서버에서 데이타를 처리하지 못했을때의 락 release
      프로세싱 카운트 -1 감소                       0 
      자료를 처리하지 못했음으로 자원카운트 1증가   1
    */
    set_sem_buf(&_release_svr_lock_op_n[0], 1, -1, SEM_UNDO | IPC_NOWAIT);
    set_sem_buf(&_release_svr_lock_op_n[1], 0, 1, IPC_NOWAIT);


    /* 초기화 되었음을 표시 */
    _is_init_lock_op = 1;
  } /* if */
  return;
} /* _init_sem_v_lock_op() */





/* 락관리 자료구조를 초기화 */
V_SEM_MANAGER get_lock_sem_v( key_t sem_key)
{
  V_SEM_MANAGER ret_val;
  L_MEMSET(&ret_val, 0, sizeof(ret_val));

  _init_sem_v_lock_op();

  /* 세마포어 생성 */
  if( get_sem_v(&ret_val, sem_key, 2) < 0 )
  {
    L_DEBUG( (LOG_APPEND, "세마포어 생성실패\n") );
    ret_val.is_valid = 0;
    return ret_val;
  } /* if */

  return ret_val;
} /* init_lock_sem_v() */



/* 읽기 락 요청 */
int get_rlock_sem_v( V_SEM_MANAGER * sem_lock)
{
  _init_sem_v_lock_op();  

  return sem_v_op(sem_lock,
                  _get_rlock_op,
                  L_ARRAY_SIZE(_get_rlock_op));
} /* get_rlock_sem_v() */



/* 읽기 락 해제 요청 */
int release_rlock_sem_v( V_SEM_MANAGER * sem_lock)
{
  _init_sem_v_lock_op();

  return sem_v_op(sem_lock,
                  _release_rlock_op,
                  L_ARRAY_SIZE(_release_rlock_op));
} /* release_rlock_sem_v() */



/* 쓰기 락 요청 */
int get_wlock_sem_v( V_SEM_MANAGER * sem_lock)
{
  _init_sem_v_lock_op();

  return sem_v_op(sem_lock,
                  _get_wlock_op,
                  L_ARRAY_SIZE(_get_wlock_op));
} /* get_wlock_sem_v() */



/* 쓰기 락 해제 요청 */
int release_wlock_sem_v( V_SEM_MANAGER * sem_lock)
{
  _init_sem_v_lock_op();

  return sem_v_op(sem_lock,
                  _release_wlock_op,
                  L_ARRAY_SIZE(_release_wlock_op));
} /* release_wlock_sem_v() */

여기서 데이타 통신용으로 사용하는 세마버퍼들은 필요없구요.
나머지 세마버퍼들은 초기화 된 이후 op에 static로 사용될 뿐입니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.