# STL 컨테이너 공유메모리 사용법

STL(Standard Template Libary) 컨테이너는 vector, deque, list, map 등의 자료구조를 가집니다.

프로세스 내 STL 컨테이너 형태에서 공유메모리에 접근하기 위해서는 boost::interprocess 라이브러리를 사용합니다.

 

C++ 표준 라이브러리는 메모리의 할당과 해제를 담당하는 특별한 객체를 할당자(Allocator)라고 하는데,
이 할당자를 통해 특별한 메모리 모델을 기술하며 직접적으로 프로그래머가 메모리를 얻는 방식을 추상화 시킵니다.

 

boost::interprocess 라이브러리를 사용하기 위해서 패키지 설치 및 공유메모리 mount 작업이 필요합니다.

테스트 환경은 CentOS를 기준으로 Qt Framework를 사용하였습니다.

 

# boost::interprocess 라이브러리 설치 및  공유메모리 확인

1. 패키지 설치

# yum -y install boost-deve


2. project 파일에 아래의 명령 추가

CONFIG += thread
LIBS += -L/usr/local/boost/libs -lrt


3. /etc/fstab 파일에 mount 명령 추가 

# vi /etc/fstab
none      /dev/shm        tmpfs   defaults,size=4G        0 0


4. 재부팅 후 확인

- /dev/shm의 크기 확인 (위 3번 과정에서 4G로 mount를 진행하였기 때문에 /dev/shm은 4G의 크기를 가집니다.)

# df -h | grep shm

- 현재 사용 중인 Shared Memory의 크기 확인 (프로그램이 동작 중 이므로 사이즈가 점차 증가하고 있습니다.)

# ls -ash /dev/shm

 

# 프로그램 실행 결과  및 소스

아래의 이미지를 기준 좌측은 공유메모리에 데이터를 Write하는 프로그램. 우측은 Read하는 프로그램 입니다.

최초 Write 프로그램에서 공유메모리의 크기를 설정하고 기록하면 Read 프로그램에서 현재 쓰여진 값을 차례로 읽어오는 과정을 거칩니다.

 

 

* Sender.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <iostream>
#include <vector>
 
typedef struct TestStruct
{
    int     firstNum;
    int     secondNum;
    int     thirdNum;
    bool    flag;
} test_struct;
 
test_struct test_value;
 
int main()
{
    using namespace boost::interprocess;
 
    try {
        shared_memory_object::remove("SharedMemory");
        //memory size adjust
        size_t szLength = 480000000;
        size_t szRequired = szLength * sizeof(test_struct);
        size_t szRequested = (size_t) (szRequired * 1.2);
 
        //create the shared memory
        managed_shared_memory segment(create_only, "SharedMemory", szRequested);
 
        typedef allocator<test_struct, managed_shared_memory::segment_manager>test_alloc;
        typedef vector<test_struct, test_alloc>test_vector;
 
        const test_alloc test_inst(segment.get_segment_manager());
        test_vector *vector_data = segment.construct<test_vector>("data")(test_inst);
 
        std::cout <<
            "Length:       " << szLength                                        << "\n" <<
            "sizeof(long): " << sizeof(test_struct)                             << "\n" <<
            "Required:     " << szRequired                                      << "\n" <<
            "Requested:    " << szRequested                                     << "\n" <<
            "Allocated:    " << segment.get_size()                              << "\n" <<
            "Overhead:     " << segment.get_size() - segment.get_free_memory()  << "\n" <<
            "Free:         " << segment.get_free_memory()                       << "\n\n";
 
        for (size_t i = 0; i < szLength; i++)
        {
            // Set "test_value" Struct Data Value
            test_value.firstNum     = i;
            test_value.secondNum    = i*10;
            test_value.thirdNum     = i*100;
            test_value.flag         = false;
 
            // Push Data to "vector<test_struct>"
            vector_data->push_back(test_value);
 
            // Print "vector<test_struct>" Value
            std::cout << "First Number: "   << vector_data->at(i).firstNum  << "\n"
                      << "Sencond Number: " << vector_data->at(i).secondNum << "\n"
                      << "Third Number: "   << vector_data->at(i).thirdNum  << "\n"
                      << "Flag : "          << vector_data->at(i).flag      << "\n";
        }
    }
    catch (...) {
        shared_memory_object::remove("SharedMemory");
        throw;
    }
 
    shared_memory_object::remove("SharedMemory");
    return 0;
}

 

* Receiver.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

#include
 <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <vector>
 
typedef struct TestStruct
{
    int     firstNum;
    int     secondNum;
    int     thirdNum;
    bool    flag;
} test_struct;
 
std::vector<test_struct> save_vector;
test_struct test_value;
 
int main()
{
    using namespace boost::interprocess;
 
    try
    {
        managed_shared_memory segment(open_only, "SharedMemory");  //segment name
 
        typedef allocator<test_struct, managed_shared_memory::segment_manager>test_alloc;
        typedef vector<test_struct, test_alloc>test_vector;
 
        test_vector *vector_data = segment.find<test_vector>("data").first;
 
        for(int i = 0; i < 100.; i++)
        {
            std::cout << "First Number: "   << vector_data->at(i).firstNum  << "\n"
                      << "Sencond Number: " << vector_data->at(i).secondNum << "\n"
                      << "Third Number: "   << vector_data->at(i).thirdNum  << "\n"
                      << "Flag : "          << vector_data->at(i).flag      << "\n";
        }
 
        segment.destroy<test_vector>("data");
    }
    catch (...)
    {
        shared_memory_object::remove("SharedMemory");
        throw;
    }
 
    shared_memory_object::remove("SharedMemory");
    return 0;
}