반응형
많은 분들이 pthread의 mutex를 thread 기반 프로그래밍에서만 사용할 수 있다고 생각합니다. 공유메모리를 사용하는 멀티 프로세스 환경에서도 Lock, Unlock을 위해 pthread_mutex를 사용할 수 있습니다. 아래 코드는 master와 slave로 나눠 2개의 프로세스가 공유메모리에 대해 접근하기 위한 방법입니다.
공유메모리에 pthread_mutex_t와 int형 변수를 가진 구조체를 올려두고 각 프로세스에선 mmap으로 매핑하여 사용합니다. 이때 자원을 함께 접근하여 사용하기 위해서는 pthread_mutex_t가 2개의 프로세스가 공유해야 하는데요, 그러긴 위해선 mutex의 attribute를 PTHREAD_PROCESS_SHARED로 설정해줘야 합니다. 아래 코드 중 69,70번 라인을 보시면 됩니다!
pthread\_mutexattr\_init(&mtx\_attr);
ret \= pthread\_mutexattr\_setpshared(&mtx\_attr, PTHREAD\_PROCESS\_SHARED);
[shm_mutex_master.c]
#include <stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#define retm_if(expr, val, msg) do { \
if (expr) \
{ \
printf("%s\n", (msg)); \
return (val); \
} \
} while(0)
#define retv_if(expr, val) do { \
if (expr) \
{ \
return (val); \
} \
} while(0)
#define rete_if(expr, val, msg) do { \
if (expr) \
{ \
printf("%s, errno : %d, errstr : %s\n", msg, errno, strerror(errno)); \
return (val); \
} \
} while(0)
#define SHM_NAME "shm_mem_test"
typedef struct shm_struct {
pthread_mutex_t mtx;
int idx;
} shm_struct_t;
static shm_struct_t* shm;
static pthread_mutexattr_t mtx_attr;
static int __init_shared_memory(void)
{
int ret;
int shm_fd;
int shm_size;
shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (shm_fd == -1) {
printf("shm_open %d %s\n", errno, strerror(errno));
return -1;
}
shm_size = sizeof(shm_struct_t);
ret = ftruncate(shm_fd, shm_size);
rete_if(ret == -1, ret, "ftruncate");
shm = (shm_struct_t*)mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
retm_if(shm == MAP_FAILED, -1, "mmap()");
close(shm_fd);
memset(shm, 0, shm_size);
pthread_mutexattr_init(&mtx_attr);
ret = pthread_mutexattr_setpshared(&mtx_attr, PTHREAD_PROCESS_SHARED);
rete_if(ret != 0, ret, "pthread_mutexattr_setpshared");
ret = pthread_mutex_init(&shm->mtx, &mtx_attr);
rete_if(ret != 0, ret, "pthread_mutex_init");
return 0;
}
static int __destory_shared_memory(void)
{
pthread_mutex_destroy(&shm->mtx);
pthread_mutexattr_destroy(&mtx_attr);
munmap(shm, sizeof(shm_struct_t));
}
int main(int argc, char* argv[])
{
int ret;
int i;
ret = __init_shared_memory();
retm_if(ret != 0, ret, "__init_shared_memory");
while (shm->idx < 10);
for (i = 0; i < 1000000; i++)
{
pthread_mutex_lock(&shm->mtx);
shm->idx++;
pthread_mutex_unlock(&shm->mtx);
}
sleep(10);
__destory_shared_memory();
return 0;
}
[shm_mutex_slave.c]
#include <stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#define retm_if(expr, val, msg) do { \
if (expr) \
{ \
printf("%s\n", (msg)); \
return (val); \
} \
} while(0)
#define retv_if(expr, val) do { \
if (expr) \
{ \
return (val); \
} \
} while(0)
#define rete_if(expr, val, msg) do { \
if (expr) \
{ \
printf("%s, errno : %d, errstr : %s\n", msg, errno, strerror(errno)); \
return (val); \
} \
} while(0)
#define SHM_NAME "shm_mem_test"
typedef struct shm_struct {
pthread_mutex_t mtx;
int idx;
} shm_struct_t;
static shm_struct_t* shm;
static int __init_shared_memory(void)
{
int ret;
int shm_fd;
int shm_size;
shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (shm_fd == -1) {
printf("shm_open %d %s\n", errno, strerror(errno));
return -1;
}
shm_size = sizeof(shm_struct_t);
ret = ftruncate(shm_fd, shm_size);
rete_if(ret == -1, ret, "ftruncate");
shm = (shm_struct_t*)mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
retm_if(shm == MAP_FAILED, -1, "mmap()");
close(shm_fd);
return 0;
}
static int __destory_shared_memory(void)
{
munmap(shm, sizeof(shm_struct_t));
}
int main(int argc, char* argv[])
{
int ret;
int i;
ret = __init_shared_memory();
retm_if(ret != 0, ret, "__init_shared_memory");
for (i = 0; i < 1000000; i++)
{
pthread_mutex_lock(&shm->mtx);
shm->idx++;
pthread_mutex_unlock(&shm->mtx);
}
__destory_shared_memory();
return 0;
}
위와 같이 컴파일 한 후 컴파일되어 생성된 ELF 파일을 shm_mutex_master와 shm_mutex_slave를 순서대로 실행해줍니다.
그럼 pthread_mutex_t 변수를 프로세스 간 공유하며 mutex를 이용해 자원을 서로 사용할 수 있습니다.
감사합니다.
반응형
'Linux > System Programming' 카테고리의 다른 글
[inotify] inotify로 watch 중인 파일을 vi(vim)나 gedit으로 수정 시 문제 (0) | 2018.12.10 |
---|---|
[TOCTOU] Time of check to time of use 문제 (0) | 2018.07.25 |
[Inotify] 파일 이벤트 감시 (2) | 2018.06.11 |
shared memory with semaphore (2) | 2018.05.19 |
[ODP] 실행시간 측정하기 (0) | 2018.05.17 |