SharedMemory_POSIX.cpp 2.6 KB

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