1 | // |
2 | // SharedMemoryImpl.cpp |
3 | // |
4 | // Library: Foundation |
5 | // Package: Processes |
6 | // Module: SharedMemoryImpl |
7 | // |
8 | // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/SharedMemory_POSIX.h" |
16 | #include "Poco/Exception.h" |
17 | #include "Poco/File.h" |
18 | #include <sys/types.h> |
19 | #include <sys/stat.h> |
20 | #include <sys/mman.h> |
21 | #include <fcntl.h> |
22 | #include <unistd.h> |
23 | |
24 | |
25 | namespace Poco { |
26 | |
27 | |
28 | SharedMemoryImpl::SharedMemoryImpl(const std::string& name, std::size_t size, SharedMemory::AccessMode mode, const void* addrHint, bool server): |
29 | _size(size), |
30 | _fd(-1), |
31 | _address(0), |
32 | _access(mode), |
33 | _name("/" ), |
34 | _fileMapped(false), |
35 | _server(server) |
36 | { |
37 | #if POCO_OS == POCO_OS_HPUX |
38 | _name.append("tmp/" ); |
39 | #endif |
40 | |
41 | _name.append(name); |
42 | |
43 | int flags = _server ? O_CREAT : 0; |
44 | if (_access == SharedMemory::AM_WRITE) |
45 | flags |= O_RDWR; |
46 | else |
47 | flags |= O_RDONLY; |
48 | |
49 | // open the shared memory segment |
50 | _fd = ::shm_open(_name.c_str(), flags, S_IRUSR | S_IWUSR); |
51 | if (_fd == -1) |
52 | throw SystemException("Cannot create shared memory object" , _name); |
53 | |
54 | // now set the correct size for the segment |
55 | if (_server && -1 == ::ftruncate(_fd, size)) |
56 | { |
57 | ::close(_fd); |
58 | _fd = -1; |
59 | ::shm_unlink(_name.c_str()); |
60 | throw SystemException("Cannot resize shared memory object" , _name); |
61 | } |
62 | map(addrHint); |
63 | } |
64 | |
65 | |
66 | SharedMemoryImpl::SharedMemoryImpl(const Poco::File& file, SharedMemory::AccessMode mode, const void* addrHint): |
67 | _size(0), |
68 | _fd(-1), |
69 | _address(0), |
70 | _access(mode), |
71 | _name(file.path()), |
72 | _fileMapped(true), |
73 | _server(false) |
74 | { |
75 | if (!file.exists() || !file.isFile()) |
76 | throw FileNotFoundException(file.path()); |
77 | |
78 | _size = file.getSize(); |
79 | int flag = O_RDONLY; |
80 | if (mode == SharedMemory::AM_WRITE) |
81 | flag = O_RDWR; |
82 | _fd = ::open(_name.c_str(), flag); |
83 | if (-1 == _fd) |
84 | throw OpenFileException("Cannot open memory mapped file" , _name); |
85 | |
86 | map(addrHint); |
87 | } |
88 | |
89 | |
90 | SharedMemoryImpl::~SharedMemoryImpl() |
91 | { |
92 | unmap(); |
93 | close(); |
94 | } |
95 | |
96 | |
97 | void SharedMemoryImpl::map(const void* addrHint) |
98 | { |
99 | int access = PROT_READ; |
100 | if (_access == SharedMemory::AM_WRITE) |
101 | access |= PROT_WRITE; |
102 | |
103 | void* addr = ::mmap(const_cast<void*>(addrHint), _size, access, MAP_SHARED, _fd, 0); |
104 | if (addr == MAP_FAILED) |
105 | throw SystemException("Cannot map file into shared memory" , _name); |
106 | |
107 | _address = static_cast<char*>(addr); |
108 | } |
109 | |
110 | |
111 | void SharedMemoryImpl::unmap() |
112 | { |
113 | if (_address) |
114 | { |
115 | ::munmap(_address, _size); |
116 | } |
117 | } |
118 | |
119 | |
120 | void SharedMemoryImpl::close() |
121 | { |
122 | if (_fd != -1) |
123 | { |
124 | ::close(_fd); |
125 | _fd = -1; |
126 | } |
127 | if (!_fileMapped && _server) |
128 | { |
129 | ::shm_unlink(_name.c_str()); |
130 | } |
131 | } |
132 | |
133 | |
134 | } // namespace Poco |
135 | |