00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "cxutils/ipc/mappedmemory.h"
00042 #include "cxutils/mutex.h"
00043 #include "cxutils/fileio.h"
00044 #include <assert.h>
00045 #include <string>
00046 #include <string.h>
00047 #include <stdlib.h>
00048 #include <iostream>
00049 #include <sstream>
00050
00051 #ifdef WIN32
00052 #include <windows.h>
00053 #ifndef MINGW
00054 #include <atlbase.h>
00055 #else
00056 #define USES_CONVERSION
00057 #define A2W(x) (x)
00058 #define W2A(x) (x)
00059 #endif
00060 #else
00061 #include <fcntl.h>
00062 #include <sys/stat.h>
00063 #include <errno.h>
00064 #include <sys/mman.h>
00065 #include <sys/types.h>
00066 #include <stdio.h>
00067 #include <stdlib.h>
00068 #include <unistd.h>
00069 #include <string.h>
00070
00071 std::string gPostFix = ".cx_shared_mem";
00072 #endif
00073
00074 using namespace CxUtils;
00075
00076 #ifndef INFINITE
00077 #define INFINITE 0xFFFFFFFF
00078 #endif
00079
00080
00081 #define CX_MAPPED_MEMORY_BASE 0
00082
00083 #ifdef WIN32
00084 #else
00085 #include <sys/ipc.h>
00086 #include <sys/shm.h>
00087 #endif
00088
00089
00095 MappedMemory::MappedMemory()
00096 {
00097 #ifdef WIN32
00098 mFileMapping = NULL;
00099 mFileSizeMapping = NULL;
00100 mpMemorySizePtr = NULL;
00101 #else
00102 mFileMapping = 0;
00103 mCreatedFlag = false;
00104 #endif
00105 memset(mMappedName, 0, sizeof(char)*MemoryNameSize);
00106 mpMemory = NULL;
00107 mLength = 0;
00108 mpMemMutex = 0;
00109 mWriteAccess = 0;
00110 }
00111
00112
00118 MappedMemory::~MappedMemory()
00119 {
00120 CloseMappedMemory();
00121 }
00122
00123
00145 int MappedMemory::OpenMappedMemory( const ID id,
00146 const unsigned int access,
00147 const unsigned int expectedSize)
00148 {
00149 std::ostringstream input;
00150 input << id;
00151 return OpenMappedMemory(input.str(), access, expectedSize);
00152 }
00153
00154
00178 int MappedMemory::OpenMappedMemory( const std::string& name,
00179 const unsigned int access,
00180 const unsigned int expectedSize)
00181 {
00182 if( name.empty() ||
00183 ( access != ReadAccess &&
00184 access != ReadWriteAccess ) )
00185 {
00186 return 0;
00187 }
00188
00189 unsigned int slength = (unsigned int)(strlen(name.c_str()));
00190 if(slength > MemoryNameSize)
00191 {
00192 return 0;
00193 }
00194
00195 #ifdef WIN32
00196
00197 USES_CONVERSION;
00198
00199 char mutName[MemoryNameSize+6];
00200 sprintf(mutName, "%s_Mutex", name.c_str());
00201 if( mpMemMutex )
00202 {
00203 delete mpMemMutex;
00204 mpMemMutex = NULL;
00205 }
00206 mpMemMutex = new Mutex(mutName);
00207 assert(mpMemMutex);
00208
00209 mpMemMutex->Lock();
00210
00211 DWORD attributes = 0;
00212 if(access == ReadAccess)
00213 attributes = FILE_MAP_READ;
00214 else
00215 attributes = FILE_MAP_READ | FILE_MAP_WRITE;
00216
00217 mFileMapping = OpenFileMapping(attributes, FALSE, A2W(name.c_str()));
00218 if(mFileMapping == NULL)
00219 {
00220 mpMemMutex->Unlock();
00221 return 0;
00222 }
00223
00224 mpMemory = (unsigned char *)MapViewOfFile(mFileMapping, attributes, 0, 0, 0);
00225 if(!mpMemory)
00226 {
00227 mpMemMutex->Unlock();
00228 delete mpMemMutex;
00229 mpMemMutex = 0;
00230 CloseMappedMemory();
00231 return 0;
00232 }
00233
00234 std::string memSizeName = name.c_str();
00235 memSizeName += "__sIzE__InF0";
00236
00237 mFileSizeMapping = OpenFileMapping(FILE_MAP_READ, FALSE, A2W(memSizeName.c_str()));
00238
00239 if(mFileSizeMapping == 0)
00240 {
00241 mLength = expectedSize;
00242 }
00243 else
00244 {
00245 mpMemorySizePtr = (unsigned char*)MapViewOfFile(mFileSizeMapping, FILE_MAP_READ, 0, 0, 0);
00246 memcpy(&mLength, mpMemorySizePtr , sizeof(unsigned int) );
00247 }
00248 memcpy(mMappedName, name.c_str(), slength);
00249 mWriteAccess = access;
00250 mPacket.Create(mpMemory + CX_MAPPED_MEMORY_BASE, mLength);
00251 mpMemMutex->Unlock();
00252
00253 return 1;
00254 #else
00255
00256 std::string smName = "/tmp/";
00257
00258
00259 smName += name.c_str();
00260 smName += gPostFix;
00261
00262
00263 char mutName[MemoryNameSize+6];
00264 sprintf(mutName, "%s", name.c_str());
00265 if( mpMemMutex )
00266 {
00267 delete mpMemMutex;
00268 mpMemMutex = NULL;
00269 }
00270 mpMemMutex = new Mutex(mutName);
00271 assert(mpMemMutex);
00272
00273 mpMemMutex->Lock();
00274
00275 key_t key;
00276 struct shmid_ds shmbuffer;
00277
00278 key = ftok(smName.c_str(), O_RDWR);
00279
00280 mFileMapping = shmget(key, CX_MAPPED_MEMORY_BASE, S_IRUSR | S_IWUSR);
00281
00282 if(mFileMapping != -1)
00283 {
00284
00285 mpMemory = (unsigned char *)shmat(mFileMapping, 0, 0);
00286
00287 shmctl(mFileMapping, IPC_STAT, &shmbuffer);
00288 if((mpMemory) != (unsigned char *)-1 && shmbuffer.shm_segsz > CX_MAPPED_MEMORY_BASE)
00289 {
00290 mLength = (unsigned int)shmbuffer.shm_segsz;
00291
00292 memcpy(mMappedName, name.c_str(), slength);
00293
00294 mWriteAccess = ReadWriteAccess;
00295 mPacket.Create(mpMemory + CX_MAPPED_MEMORY_BASE, mLength);
00296 mpMemMutex->Unlock();
00297 return 1;
00298 }
00299 }
00300
00301 mpMemMutex->Unlock();
00302
00303 return 0;
00304 #endif
00305 }
00306
00307
00319 int MappedMemory::CreateMappedMemory(const ID id,
00320 const unsigned int size)
00321 {
00322 std::ostringstream input;
00323 input << id;
00324 return CreateMappedMemory(input.str(), size);
00325 }
00326
00327
00340 int MappedMemory::CreateMappedMemory(const std::string& name,
00341 const unsigned int size)
00342 {
00343 if( name.empty() )
00344 {
00345 return 0;
00346 }
00347
00348 unsigned int slength = (unsigned int)(strlen(name.c_str()));
00349 if(slength > MemoryNameSize)
00350 {
00351 return 0;
00352 }
00353
00354 #ifdef WIN32
00355 DWORD attributes = 0;
00356 int memExists;
00357
00358 USES_CONVERSION;
00359
00360
00361 char mutName[MemoryNameSize+6];
00362 sprintf(mutName, "%s_Mutex", name.c_str());
00363 if( mpMemMutex )
00364 {
00365 delete mpMemMutex;
00366 mpMemMutex = NULL;
00367 }
00368 mpMemMutex = new Mutex(mutName);
00369 assert(mpMemMutex);
00370
00371 mpMemMutex->Lock();
00372
00373 mFileMapping = CreateFileMapping( INVALID_HANDLE_VALUE,
00374 NULL,
00375 PAGE_READWRITE,
00376 0,
00377 sizeof(unsigned char)*size + CX_MAPPED_MEMORY_BASE,
00378 A2W(name.c_str()));
00379 memExists = GetLastError();
00380
00381
00382
00383
00384 if(memExists == ERROR_ALREADY_EXISTS)
00385 {
00386 mpMemMutex->Unlock();
00387 return 0;
00388 }
00389
00390 if(mFileMapping == NULL)
00391 {
00392 mpMemMutex->Unlock();
00393 return 0;
00394 }
00395
00396 memcpy(mMappedName, name.c_str(), slength);
00397
00398 std::string memSizeName = name.c_str();
00399 memSizeName += "__sIzE__InF0";
00400 mFileSizeMapping = CreateFileMapping(INVALID_HANDLE_VALUE,
00401 NULL,
00402 PAGE_READWRITE,
00403 0,
00404 sizeof(unsigned int),
00405 A2W(memSizeName.c_str()));
00406 mpMemorySizePtr = (unsigned char*)MapViewOfFile(mFileSizeMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
00407
00408
00409 mpMemory = (unsigned char *)MapViewOfFile(mFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
00410 if(!mpMemory)
00411 {
00412 mpMemMutex->Unlock();
00413 delete mpMemMutex;
00414 mpMemMutex = NULL;
00415 CloseMappedMemory();
00416 return 0;
00417 }
00418
00419
00420
00421 mLength = sizeof(unsigned char)*size + CX_MAPPED_MEMORY_BASE;
00422 memcpy(mpMemorySizePtr, &mLength, sizeof(unsigned int));
00423 memcpy(mMappedName, name.c_str(), slength);
00424
00425 mWriteAccess = ReadWriteAccess;
00426 mPacket.Create(mpMemory + CX_MAPPED_MEMORY_BASE, mLength);
00427
00428
00429 mpMemMutex->Unlock();
00430
00431 return 1;
00432 #else
00433
00434 std::string smName = "/tmp/";
00435 FILE* fp;
00436
00437 smName += name.c_str();
00438 smName += gPostFix;
00439
00440 fp = fopen(smName.c_str(), "w+b");
00441 if(fp == NULL)
00442 {
00443 return 0;
00444 }
00445 fclose(fp);
00446
00447
00448 char mutName[MemoryNameSize+6];
00449 sprintf(mutName, "%s", name.c_str());
00450 if( mpMemMutex )
00451 {
00452 delete mpMemMutex;
00453 mpMemMutex = NULL;
00454 }
00455 mpMemMutex = new Mutex(mutName);
00456 assert(mpMemMutex);
00457
00458 mpMemMutex->Lock();
00459
00460 key_t key;
00461
00462 struct shmid_ds shmbuffer;
00463
00464 mLength = CX_MAPPED_MEMORY_BASE + size;
00465
00466 key = ftok(smName.c_str(), O_RDWR);
00467
00468 mFileMapping = shmget(key, mLength, IPC_CREAT | S_IRUSR | S_IWUSR);
00469 shmctl(mFileMapping, IPC_STAT, &shmbuffer);
00470 if(mFileMapping >= 0 && shmbuffer.shm_nattch == 0)
00471 {
00472
00473 if(shmbuffer.shm_segsz != mLength)
00474 {
00475 shmctl(mFileMapping, IPC_RMID, NULL);
00476 mFileMapping = shmget(key, mLength, IPC_CREAT | S_IRUSR | S_IWUSR);
00477 }
00478
00479 mpMemory = (unsigned char *)shmat(mFileMapping, 0, 0);
00480
00481 shmctl(mFileMapping, IPC_STAT, &shmbuffer);
00482 if((mpMemory) != (unsigned char *)(-1) && mLength == (unsigned int)shmbuffer.shm_segsz)
00483 {
00484
00485 memcpy(mMappedName, name.c_str(), slength);
00486
00487 mPacket.Create(mpMemory + CX_MAPPED_MEMORY_BASE, mLength);
00488 mWriteAccess = ReadWriteAccess;
00489 mCreatedFlag = true;
00490 mpMemMutex->Unlock();
00491
00492 return 1;
00493 }
00494 }
00495
00496 mpMemMutex->Unlock();
00497
00498 return 0;
00499 #endif
00500 }
00501
00510 int MappedMemory::CloseMappedMemory()
00511 {
00512 int result = 1;
00513
00514 Lock();
00515
00516 mPacket.Clear();
00517
00518 #ifdef WIN32
00519 if(mpMemory)
00520 {
00521 UnmapViewOfFile(mpMemory);
00522 mpMemory = NULL;
00523 }
00524 if(mFileMapping)
00525 {
00526 CloseHandle(mFileMapping);
00527 mFileMapping = NULL;
00528 }
00529 if(mpMemorySizePtr)
00530 {
00531 UnmapViewOfFile(mpMemorySizePtr);
00532 mpMemorySizePtr = NULL;
00533 }
00534 if(mFileSizeMapping)
00535 {
00536 CloseHandle(mFileSizeMapping);
00537 mFileSizeMapping = NULL;
00538 }
00539 result = 1;
00540 #else
00541
00542 if(mpMemory)
00543 {
00544
00545 shmdt(mpMemory);
00546 }
00547 if(mFileMapping > 0)
00548 {
00549 struct shmid_ds shminfo;
00550 shmctl(mFileMapping, IPC_STAT, &shminfo);
00551
00552
00553
00554 if(shminfo.shm_nattch == 0)
00555 {
00556
00557
00558 shmctl(mFileMapping, IPC_RMID, 0);
00559
00560 std::string smName = "/tmp/";
00561 smName += mMappedName;
00562 smName += gPostFix;
00563 FileIO::DeleteFiles(smName);
00564 }
00565 }
00566 mpMemory = NULL;
00567 mFileMapping = 0;
00568 mCreatedFlag = false;
00569 #endif
00570
00571 Unlock();
00572
00573 if(mpMemMutex)
00574 {
00575 delete mpMemMutex;
00576 mpMemMutex = 0;
00577 }
00578
00579 memset(mMappedName, 0, sizeof(char)*MemoryNameSize);
00580 mLength = 0;
00581 mWriteAccess = 0;
00582 mFileMapping = 0;
00583
00584 return result;
00585 }
00586
00587
00601 int MappedMemory::DeleteMappedMemory(const std::string& name)
00602 {
00603 #ifdef WIN32
00604
00605
00606 return 1;
00607 #else
00608
00609
00610 key_t key;
00611 int fileMapping = 0;
00612 std::string smName;
00613 key = ftok(name.c_str(), O_RDWR);
00614
00615
00616 fileMapping = shmget(key, 1, S_IRUSR | S_IWUSR);
00617 if(fileMapping == -1)
00618 {
00619 smName = "/tmp/";
00620 smName += name.c_str();
00621 smName += gPostFix;
00622 key = ftok(smName.c_str(), O_RDWR);
00623
00624 fileMapping = shmget(key, 1, S_IRUSR | S_IWUSR);
00625 }
00626
00627 if(fileMapping != -1)
00628 {
00629
00630 shmctl(fileMapping, IPC_RMID, 0);
00631 if(smName.size() > 0)
00632 {
00633
00634 FileIO::DeleteFiles(smName);
00635 }
00636 return 1;
00637 }
00638 if(smName.size() > 0)
00639 {
00640
00641 FileIO::DeleteFiles(smName);
00642 }
00643
00644 #endif
00645
00646 return 0;
00647 }
00648
00649
00664 int MappedMemory::Lock(unsigned long wait) const
00665 {
00666 if(mpMemMutex)
00667 {
00668 return mpMemMutex->Lock(wait);
00669 }
00670 return 0;
00671 }
00672
00673
00685 int MappedMemory::Unlock() const
00686 {
00687 if(mpMemMutex)
00688 {
00689 mpMemMutex->Unlock();
00690 return 1;
00691 }
00692 return 0;
00693 }
00694
00695
00705 const Packet* MappedMemory::operator ->() const
00706 {
00707 return mPacket.GetData();
00708 }
00709
00710
00720 Packet* MappedMemory::operator ->()
00721 {
00722 return mPacket.GetData();
00723 }
00724
00725
00735 const Packet* MappedMemory::GetData() const
00736 {
00737 return mPacket.GetData();
00738 }
00739
00740
00750 Packet* MappedMemory::GetData()
00751 {
00752 return mPacket.GetData();
00753 }
00754
00755
00770 int MappedMemory::Copy(const unsigned int p1, const unsigned int p2)
00771 {
00772 if(!mpMemory || !mLength)
00773 {
00774 return 0;
00775 }
00776
00777 unsigned int len = mLength - CX_MAPPED_MEMORY_BASE;
00778 if(p2 >= p1 || p1 >= len || p2 >= len)
00779 {
00780 return 0;
00781 }
00782
00783 memmove(&mpMemory[p2 + CX_MAPPED_MEMORY_BASE],
00784 &mpMemory[p1 + CX_MAPPED_MEMORY_BASE],
00785 sizeof(unsigned char)*(len - p1));
00786
00787 return 1;
00788 }
00789
00790
00796 bool MappedMemory::IsOpen() const
00797 {
00798 return mpMemory != NULL;
00799 }
00800
00809 unsigned char *MappedMemory::GetMemory()
00810 {
00811 if(mpMemory)
00812 {
00813 return mpMemory + CX_MAPPED_MEMORY_BASE;
00814 }
00815 return 0;
00816 }
00817
00818
00827 const unsigned char *MappedMemory::GetMemory() const
00828 {
00829 if(mpMemory)
00830 {
00831 return mpMemory + CX_MAPPED_MEMORY_BASE;
00832 }
00833 return 0;
00834 }
00835
00836
00842 unsigned int MappedMemory::Length() const
00843 {
00844 if(mpMemory && mLength)
00845 {
00846 return mLength - CX_MAPPED_MEMORY_BASE;
00847 }
00848 return 0;
00849 }
00850
00851
00863 bool MappedMemory::IsMemOpen(const std::string& name)
00864 {
00865 bool result = false;
00866
00867 #ifdef WIN32
00868 HANDLE fileMapping;
00869 USES_CONVERSION;
00870 fileMapping = OpenFileMapping(FILE_MAP_READ, FALSE, A2W(name.c_str()));
00871 if(fileMapping != NULL)
00872 {
00873 result = true;
00874 CloseHandle(fileMapping);
00875 }
00876
00877 #else
00878 MappedMemory mem;
00879 if(mem.OpenMappedMemory(name))
00880 {
00881 result = true;
00882 }
00883 #endif
00884
00885 return result;
00886 }
00887
00888