1 | //
|
---|
2 | // Purpose: Play arround with shared memory and the permissions to allocate it
|
---|
3 | //
|
---|
4 |
|
---|
5 | #include <sys/shm.h> // shmget,...
|
---|
6 | #include <iostream>
|
---|
7 | #include <string>
|
---|
8 | #include <cerrno> // errno
|
---|
9 | #include <cstring> // strerror
|
---|
10 | #include <cstdlib> // system
|
---|
11 |
|
---|
12 | #include <boost/cstdint.hpp>
|
---|
13 | #include <boost/lexical_cast.hpp>
|
---|
14 | #include <boost/interprocess/managed_shared_memory.hpp>
|
---|
15 |
|
---|
16 | static const int invalid_shm_id = -1;
|
---|
17 | static const int invalid_shm_pointer = -1;
|
---|
18 |
|
---|
19 | static const int shm_key = 0x12345;
|
---|
20 | static const int shm_size = 0x1000;
|
---|
21 | static const std::string shm_key_for_boost =
|
---|
22 | boost::lexical_cast<std::string>(shm_key);
|
---|
23 |
|
---|
24 | static const int shm_boost_margin = 0x100;
|
---|
25 |
|
---|
26 |
|
---|
27 | boost::uint8_t * shm_create_unix(int & shm_id)
|
---|
28 | {
|
---|
29 | //
|
---|
30 | // create global shared memory and get an id of it
|
---|
31 | // (identified by the given key)
|
---|
32 | //
|
---|
33 | shm_id = shmget(shm_key,
|
---|
34 | shm_size,
|
---|
35 | 0600 | IPC_CREAT | IPC_EXCL);
|
---|
36 |
|
---|
37 | if (shm_id == invalid_shm_id)
|
---|
38 | {
|
---|
39 | std::cerr << "Could not get global shared memory for key="
|
---|
40 | << shm_key
|
---|
41 | << ": " << strerror(errno)
|
---|
42 | << std::endl;
|
---|
43 | return 0;
|
---|
44 | }
|
---|
45 |
|
---|
46 | //
|
---|
47 | // attach the global shared memory
|
---|
48 | // (associated with the given id, not the key)
|
---|
49 | //
|
---|
50 | boost::uint8_t * shm =
|
---|
51 | static_cast<boost::uint8_t *>(shmat(shm_id,
|
---|
52 | static_cast<void*>(0),
|
---|
53 | 0));
|
---|
54 |
|
---|
55 | if (shm == reinterpret_cast<void *>(invalid_shm_pointer))
|
---|
56 | {
|
---|
57 | std::cerr << "Could not attach global shared memory for id="
|
---|
58 | << boost::lexical_cast<std::string>(shm_id)
|
---|
59 | << ", key="
|
---|
60 | << boost::lexical_cast<std::string>(shm_key)
|
---|
61 | << ": " << strerror(errno)
|
---|
62 | << std::endl;
|
---|
63 | return 0;
|
---|
64 | }
|
---|
65 |
|
---|
66 | return shm;
|
---|
67 | }
|
---|
68 |
|
---|
69 | void shm_free_unix(boost::uint8_t * shm, int shm_id)
|
---|
70 | {
|
---|
71 | int ret = shmdt(shm);
|
---|
72 |
|
---|
73 | if (ret == -1)
|
---|
74 | {
|
---|
75 | std::cerr << "Detaching of shared memory (0x"
|
---|
76 | << std::hex << shm << std::dec
|
---|
77 | << ") failed. id=" << shm_id
|
---|
78 | << ": " << strerror(errno)
|
---|
79 | << std::endl;
|
---|
80 | return;
|
---|
81 | }
|
---|
82 |
|
---|
83 | ret = shmctl(shm_id, IPC_RMID, NULL);
|
---|
84 |
|
---|
85 | if (ret != 0)
|
---|
86 | {
|
---|
87 | std::cerr << "Deleting of shared memory failed. id="
|
---|
88 | << boost::lexical_cast<std::string>(shm_id)
|
---|
89 | << ": " << strerror(errno)
|
---|
90 | << std::endl;
|
---|
91 | }
|
---|
92 | }
|
---|
93 |
|
---|
94 | boost::uint8_t * shm_create_boost()
|
---|
95 | {
|
---|
96 | using namespace boost::interprocess;
|
---|
97 |
|
---|
98 | //A special shared memory from which we are
|
---|
99 | //able to allocate raw memory buffers.
|
---|
100 | //First remove any old shared memory of the same name, create
|
---|
101 | //the shared memory segment and initialize needed resources
|
---|
102 | shared_memory_object::remove(shm_key_for_boost.c_str());
|
---|
103 |
|
---|
104 | void * shm = 0;
|
---|
105 |
|
---|
106 | try
|
---|
107 | {
|
---|
108 | // boost also needs some private space in the shared memory
|
---|
109 | managed_shared_memory segment(create_only,
|
---|
110 | shm_key_for_boost.c_str(),
|
---|
111 | shm_size+shm_boost_margin);
|
---|
112 |
|
---|
113 | //Allocate a portion of the segment
|
---|
114 | shm = segment.allocate(shm_size);
|
---|
115 | }
|
---|
116 | catch(...)
|
---|
117 | {
|
---|
118 | shared_memory_object::remove(shm_key_for_boost.c_str());
|
---|
119 | throw;
|
---|
120 | }
|
---|
121 |
|
---|
122 | return static_cast<boost::uint8_t *>(shm);
|
---|
123 | }
|
---|
124 |
|
---|
125 | void shm_free_boost(boost::uint8_t * shm)
|
---|
126 | {
|
---|
127 | using namespace boost::interprocess;
|
---|
128 |
|
---|
129 | try
|
---|
130 | {
|
---|
131 | managed_shared_memory segment(open_only,
|
---|
132 | shm_key_for_boost.c_str());
|
---|
133 |
|
---|
134 | segment.deallocate(shm);
|
---|
135 | }
|
---|
136 | catch(...)
|
---|
137 | {
|
---|
138 | shared_memory_object::remove(shm_key_for_boost.c_str());
|
---|
139 | throw;
|
---|
140 | }
|
---|
141 |
|
---|
142 | shared_memory_object::remove(shm_key_for_boost.c_str());
|
---|
143 | }
|
---|
144 |
|
---|
145 | int main(int argc, char * argv[])
|
---|
146 | {
|
---|
147 | if (argc <= 1)
|
---|
148 | {
|
---|
149 | std::cout << "unix way:" << std::endl;
|
---|
150 |
|
---|
151 | int shm_id = invalid_shm_id;
|
---|
152 |
|
---|
153 | boost::uint8_t * const shm = shm_create_unix(shm_id);
|
---|
154 |
|
---|
155 | std::cout << "Got shm=" << static_cast<void *>(shm) << std::endl;
|
---|
156 |
|
---|
157 | system("ipcs -m");
|
---|
158 |
|
---|
159 | shm_free_unix(shm, shm_id);
|
---|
160 | }
|
---|
161 | else
|
---|
162 | {
|
---|
163 | std::cout << "Boost way:" << std::endl;
|
---|
164 |
|
---|
165 | boost::uint8_t * const shm = shm_create_boost();
|
---|
166 |
|
---|
167 | std::cout << "Got shm=" << static_cast<void *>(shm) << std::endl;
|
---|
168 |
|
---|
169 | system("ipcs -m");
|
---|
170 |
|
---|
171 | shm_free_boost(shm);
|
---|
172 | }
|
---|
173 |
|
---|
174 | return 0;
|
---|
175 | }
|
---|