[질문]프로세스간 뮤텍스동기화 에 대해서

wsong의 이미지

프로세스2개와 공유메모리생성후, 공유메모리위의 뮤텍스로 동기화에 대한 간단한 테스트 프로그램인데, 동기화가 안되네요.

<시스템 스레드라이브러리 확인>
이 확인으로 NPTL이 적용된걸로 봐도되나요?

getconf GNU_LIBPTHREAD_VERSION
NPTL 2.3.4

<헤더>
단순히 공유메모리용 구조체

#include <pthread.h>
typedef struct shm_struct {
  pthread_mutex_t  mtx;
  pthread_cond_t   cond;
  int i, j;
} shm_struct_t;

<프로그램1>
공유메모리생성후 뮤텍스,조건변수 초기화합니다.
락을 걸고 공유메모리의 변수를 1더하고, 60초간 sleep하면서 빙빙돕니다. 이 60초동안 프로그램2가 접근못하는것을 확인하려고 합니다.

인클루드부분 생략...
#include "testpro.h"
 
shm_struct_t *g_shm;
pthread_mutexattr_t mtx_attr;
pthread_condattr_t cond_attr;
 
int shm_init() {
  int fd;
  int ret = 0;
  int shm_size;
  fd = shm_open("/testpro", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IROTH);
  if (fd == -1) {
    fprintf(stderr, "shm_open() error\n");
    return fd;
  }
  shm_size = sizeof(shm_struct_t);
  ret = ftruncate(fd, shm_size);
  if (ret == -1) {
    fprintf(stderr, "ftruncate() failed. errno=%d\n", errno);
    return ret;
  }
  g_shm = (shm_struct_t *)mmap(NULL, shm_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  if (g_shm == MAP_FAILED) {
    fprintf(stderr, "mmap() failed\n");
    return -1;
  }
  close(fd);
  pthread_mutexattr_init(&mtx_attr);
  ret = pthread_mutexattr_setpshared(&mtx_attr, PTHREAD_PROCESS_SHARED);
  if (ret) {
    fprintf(stderr, "pthread_mutexattr_settype() failed.(errno=%d)\n", errno);
    return ret;
  }
  pthread_mutex_init(&g_shm->mtx, &mtx_attr);
 
  pthread_condattr_init(&cond_attr);
  ret = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
  if (ret) {
    fprintf(stderr, "pthread_mutexattr_setpshared() failed. (errno=%d)\n", errno);
    return ret;
  }
  pthread_cond_init(&g_shm->cond, &cond_attr);
 
  return ret;
}
 
int 
main()
{
  int ret = 0; 
  ret = shm_init();
  if (ret) {
    fprintf(stderr, "shm_init() failed. \n");
    return ret;
  }
 
  while (1) {
    pthread_mutex_lock(&g_shm->mtx);
    g_shm->i++;   
    fprintf(stdout, "i = %d, j = %d\n", g_shm->i, g_shm->j);
    sleep(60);
    pthread_mutex_unlock(&g_shm->mtx);
  }
  return ret;
}

<프로그램2>
공유메모리생성(항상 프로그램1이 공유메모리를 생성한 후에 실행됨.이미 생성된 공유메모리에 대해서는 참조를 하게됨.).
락을 걸고 공유메모리의 변수를 1더하고, 5초간 sleep하면서 빙빙돕니다.프로그램1이 락을 걸고 60초 sleep하기 때문에, 프로그램2가 이 60초동안 접근못하는 것을 확인해서, 프로세스간 뮤텍스 사용에 문제 없는 것을 확인하려고 합니다.

헤더부분 생략...
#include "testpro.h"
shm_struct_t *g_shm;
pthread_mutexattr_t mtx_attr;
pthread_condattr_t cond_attr;
 
int shm_init() {
  int fd;
  int ret = 0;  
  int shm_size;
 
  fd = shm_open("/testpro", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IROTH);
  if (fd == -1) {
    fprintf(stderr, "shm_open() error\n");
    return fd;
  }
  shm_size = sizeof(shm_struct_t);
  ret = ftruncate(fd, shm_size);
  if (ret == -1) {
    fprintf(stderr, "ftruncate() failed. errno=%d\n", errno);
    return ret;
  }
  g_shm = (shm_struct_t *)mmap(NULL, shm_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  if (g_shm == MAP_FAILED) {
    fprintf(stderr, "mmap() failed\n");
    return -1;
  }
  close(fd);
 
  return ret;
}
 
int 
main()
{
  int ret = 0; 
 
  ret = shm_init();
  if (ret) {
    fprintf(stderr, "shm_init() failed. \n");
    return ret;
  }
  while(1) {
    pthread_mutex_lock(&g_shm->mtx);
    g_shm->i++;   
    fprintf(stdout, "i = %d, j = %d\n", g_shm->i, g_shm->j);
    sleep(5);
    pthread_mutex_unlock(&g_shm->mtx);
  }
  return ret;
}

실행순서는 프로그램1->프로그램2 으로 실행했습니다.
결과는 프로그램1이60초간 sleep하는 동안에 프로그램2가 공유메모리의 변수에 접근을 못하는것을 확인하려고 하는데, 프로그램2가 접근해서 값을 변경해버리는 군요.

혹시 문제가 짐작가시는 분은 알려주세요ㅠㅠ

cinsk의 이미지

흠.. 뭔가 이상한데요..

IPC와 thread에 대해서 실수하신 것 같네요.

pthread_*로 시작하는 모든 함수들은 한 process에서 여러 thread를 위한 것입니다. 따라서 pthread의 mutex는 한 process에서 여러 thread들 사이에 동기화를 위한 것입니다. 여러 process사이에 일어나는 동기화하고는 아무런 관련이 없습니다.

질문하신 shared memory는 여러 process 사이에 memory를 공유하기 위한 것으로, 이 process 사이에 동기화가 필요하다면 IPC에서 제공하는 동기화 기능을 써야 합니다. pipe나 message queue, 또는 semaphore가 있습니다.

요약하면, thread를 쓰지 않고 multi-process를 쓴다면 pthread_로 시작하는 함수들을 쓸 이유가 없습니다.

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

wsong의 이미지

이 부분이 뮤텍스의 속성을 설정하는 부분인데. pthread_mutexattr_setpshared()함수의 2번쩨 인수로 PTHREAD_PROCESS_SHARED를 주면, 프로세스간에서 사용할 수 있다는 걸로 알고 있습니다.

  pthread_mutexattr_init(&mtx_attr);
  ret = pthread_mutexattr_setpshared(&mtx_attr, PTHREAD_PROCESS_SHARED);
  if (ret) {
    fprintf(stderr, "pthread_mutexattr_settype() failed.(errno=%d)\n", errno);
    return ret;
  }
  pthread_mutex_init(&g_shm->mtx, &mtx_attr);
 
  pthread_condattr_init(&cond_attr);
  ret = pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
  if (ret) {
    fprintf(stderr, "pthread_mutexattr_setpshared() failed. (errno=%d)\n", errno);
    return ret;
  }
  pthread_cond_init(&g_shm->cond, &cond_attr);

솔라리스는 전부터 지원했었는데, 리눅스에서는 2.6버전에서부터 지원하는 거 같은데, 어디가 잘못된건지 잘안되네요

cinsk의 이미지

-_-;;;; 무식이 탄로나는 순간이군요. -_-;;;;;

먼저, _POSIX_THREAD_PROCESS_SHARED가 정의되었는지, 확인해보시기 바랍니다.

$ getconf _POSIX_THREAD_PROCESS_SHARED
200112
$ _

그리고 올리신 코드, 제 시스템에서는 정상적으로 되는 것 같네요. 단지, wsong님의 ntpl version이 조금 낮은게 걸리긴 합니다:

$ getconf GNU_LIBPTHREAD_VERSION
NPTL 2.8
$ _

--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

mon12key의 이미지

저도 궁금해서 테스트 해봤습니다.
wsong님과 동일한 ntpl version(NPTL 2.3.4)인데,
정상적으로 lock/unlock 동작합니다.

<-_-; sleep (1) 로 변경한거 빼고는 동일합니다.>

$ ./test &
T1: i = 289, j = 0
T1: i = 290, j = 0
$ ./test1
T1: i = 291, j = 0
T2: i = 292, j = 0
T1: i = 293, j = 0
T2: i = 294, j = 0
T1: i = 295, j = 0
T2: i = 296, j = 0
T1: i = 297, j = 0
T2: i = 298, j = 0
T1: i = 299, j = 0
T2: i = 300, j = 0
T1: i = 301, j = 0
T2: i = 302, j = 0
T1: i = 303, j = 0
T2: i = 304, j = 0
T1: i = 305, j = 0
T2: i = 306, j = 0
T1: i = 307, j = 0
T2: i = 308, j = 0
T1: i = 309, j = 0
T2: i = 310, j = 0
T1: i = 311, j = 0
T2: i = 312, j = 0

baboda4u의 이미지

잘되신다니...하수의 글은 접어야 겠군효 ^^ ㅋ

============================
Stay Hungry, Stay Foolish

============================
Stay Hungry, Stay Foolish

익명 사용자의 이미지

sleep 위치가 틀렸어요~~~

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.