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
25namespace Poco {
26
27
28SharedMemoryImpl::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
66SharedMemoryImpl::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
90SharedMemoryImpl::~SharedMemoryImpl()
91{
92 unmap();
93 close();
94}
95
96
97void 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
111void SharedMemoryImpl::unmap()
112{
113 if (_address)
114 {
115 ::munmap(_address, _size);
116 }
117}
118
119
120void 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