1

CreateFileMapping() および MapViewOfFile() で作成された名前付き共有メモリを使用して、Master exe によって制御される一連の Slave exe があります。

私は Visual Studio を介してマスターをデバッグしていました。必要なものを取得したら、Visual Studio に「デバッグを停止する」ように指示しました。その名前付き共有メモリがアクティブなままで、再起動後もまだそこにあるため、悪い動きです!

エラーコードを見て名前付き共有メモリを認識しようとしましたが、それが 183 (既に存在する) であることを確認し、既存の名前付き共有メモリを要求しましたが、失敗しました。

私はどちらの方法でも満足しています: 既に存在することがわかった場合は削除/削除するか、既に存在することがわかった場合は再利用します。現在、私は立ち往生しています。別の名前を作成することもできると思いますが、すでに存在するそのいまいましい名前は、おそらく永遠にそこにとどまります.

とにかく、これが私の名前付き共有メモリ制御ロジックを定義する C++ クラスです。

enum ServerSharedMemReturnCodes {
    Success,                    // everything worked!
    SharedMemAlreadyGrabbed,    // EnableSharedMemoryAccess() error: _mapFile was not NULL!
    OpenFileMappingFailed,      // EnableSharedMemoryAccess() error: OpenFileMapping() filed!
    MapViewOfFileFailed         // EnableSharedMemoryAccess() error: MapViewOfFile() filed!
};

class ServerSharedMem {
public:
    ServerSharedMem() {
        _mapFile         = NULL;
        _serverCommLinks = NULL;
    }
    ~ServerSharedMem() {
        // Deactivate(); called explicitly at shutdown rather than here
    }

    /* our Named Shared Memory needs to be "activated" by the Master (installed to shared virtual memory). This does that. */
    inline int Activate( void ) {
        char *caller = "ServerSharedMem::Activate";

        if (_mapFile != NULL) {
            DebugMessage( caller, "Named Shared Memory already activated!" );
            return false;
        }

        TCHAR smName[]      = TEXT(CEX_SHAREDMEM_NAME);
        int   sharedMemSize = sizeof(ServerCommLink) * CEX_MAX_SERVER_COUNT;

        // debug logic: print out size and name:
        size_t convertedChars = 0;
        char   bsjnk[1024];
        errno_t err = wcstombs_s( &convertedChars, bsjnk, 1024, smName, sizeof(smName));
        if (err != 0) {
            DebugMessage( caller, "wcstombs_s  failed!" );
        } 
        char bsjnk2[1024];
        sprintf_s( bsjnk2, 1024, "sharedMemSize is '%d' bytes and smName is '%s'", sharedMemSize, bsjnk );
        DebugMessage( caller, bsjnk2 ); // size is 16832, name is "Global\CEX_ActiveTasks"


        // let's create a Named Shared Memory block:
        _mapFile = CreateFileMapping( INVALID_HANDLE_VALUE,   // request a paging file
                                      NULL,                   // default security
                                      PAGE_READWRITE | SEC_COMMIT, // read/write access and hold entirely in RAM
                                      0,                      // high-order DWORD of max file size
                                      sharedMemSize,          // low-order DWORD of max file size
                                      smName );               // name of our named shared memory
        if (_mapFile == NULL) {
            DebugMessage( caller, "failed to create Named Shared Memory!" );

            DWORD errCode = GetLastError();
            if (errCode == 183) { // already exists! we did not shutdown cleanly
               DebugMessage( caller, "It appears to already exist! Attempting to grab it!" );
               ServerSharedMemReturnCodes retCode = EnableSharedMemoryAccess();
               if (retCode == Success) {
                  DebugMessage( caller, "Yes! Got it!" );
                  for (int i = 0; i < CEX_MAX_SERVER_COUNT; i++) {
                      _serverCommLinks[i].Init();
                      _serverCommLinks[i].SetServerId( i );
                  }
                  return true;
               }
               static CHAR errBuffer[CEX_CMDBUFFER_SIZE];
                va_list     errArgs[256];
                FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,NULL,errCode,0,errBuffer,CEX_CMDBUFFER_SIZE,errArgs);
                DebugMessage( caller, errBuffer );
                sprintf_s( errBuffer, CEX_CMDBUFFER_SIZE, "error code is '%d'", errCode );
                DebugMessage( caller, errBuffer ); // still 183, already exists
            }
            /*
            static CHAR errBuffer[CEX_CMDBUFFER_SIZE];
            va_list     errArgs[256];
            FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,NULL,errCode,0,errBuffer,CEX_CMDBUFFER_SIZE,errArgs);
            DebugMessage( caller, errBuffer );
            sprintf_s( errBuffer, CEX_CMDBUFFER_SIZE, "error code is '%d'", errCode );
            DebugMessage( caller, errBuffer ); */
            return false;
        }
        else {
            _serverCommLinks = (ServerCommLink *)MapViewOfFile(_mapFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
            if (_serverCommLinks == NULL) {
                CloseHandle(_mapFile);
                _mapFile = NULL;
                DebugMessage( caller, "MapViewOfFile() failed!" );
                return false;
            }
            else {
                for (int i = 0; i < CEX_MAX_SERVER_COUNT; i++) {
                    _serverCommLinks[i].Init();
                    _serverCommLinks[i].SetServerId( i );
                }
                return true;
            }
        }
    }

    /* upon program shutdown, Named Shared Memory needs to be removed from Shared Virtual Memory. This does that. */
    inline void Deactivate( void ) {
        char *caller = "ServerSharedMem::Deactivate";
        if (_mapFile) {
            if (_serverCommLinks) {
                UnmapViewOfFile( _serverCommLinks );
                _serverCommLinks = NULL;
                DebugMessage( caller, "Unmapped Named Shared Memory view." );
            }
            CloseHandle(_mapFile);
            _mapFile = NULL;
            DebugMessage( caller, "Closed Named Shared Memory handle." );
        }
    }

    /* Slaves use this to gain access to the Named Shared Memory setup by their Master */
    inline ServerSharedMemReturnCodes EnableSharedMemoryAccess( void ) {
        if (_mapFile != NULL) {
            return SharedMemAlreadyGrabbed;
        }
        TCHAR smName[] = TEXT(CEX_SHAREDMEM_NAME);
        _mapFile = OpenFileMapping( FILE_MAP_READ | FILE_MAP_WRITE, FALSE, smName );
        if (_mapFile == NULL) {
            return OpenFileMappingFailed;
        }
        else {
            _serverCommLinks = (ServerCommLink *)MapViewOfFile( _mapFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0 );
            return Success;
        }
    }

    /* Slaves use this to release their hold on their view of the Named Shared Memory */
    inline void ReleaseSharedMemoryAccess( void ) {
        char *caller = "ServerSharedMem::ReleaseSharedMemoryAccess";
        if (_mapFile != NULL) {
            if (_serverCommLinks != NULL) {
                UnmapViewOfFile( _serverCommLinks );
                _serverCommLinks = NULL;
                DebugMessage( caller, "Unmapped Named Shared Memory view." );
            }
            else DebugMessage( caller, "No active Named Shared Memory view!" );
            CloseHandle(_mapFile);
            DebugMessage( caller, "Closed Named Shared Memory handle." );
        }
        else DebugMessage( caller, "No Named Shared Memory!" );
    }

    /* pass in a return code, get back a string describing the code */
    inline char *ReturnCodeInfo( ServerSharedMemReturnCodes code ) {
        switch (code) {
        case Success:                 return "Success.";
        case SharedMemAlreadyGrabbed: return "Shared memory access has already been enabled.";
        case OpenFileMappingFailed:   return "Unable to open Named Shared Memory!";
        case MapViewOfFileFailed:     return "Unable to map view of Named Shared Memory!";
        default:                      return "Unknown return code!!!";
        }
    }

    inline int Active( void ) { return(_serverCommLinks ? true : false); }

    /* returns the requested server;s communication link if Named Shared Memory is activated/enabled */
    inline ServerCommLink *GetServerCommLink( int serverId ) {
        if (!_serverCommLinks)
            return NULL;
        if ((serverId >= 0) && (serverId < CEX_MAX_SERVER_COUNT)) {
            return &_serverCommLinks[serverId];
        }
        return NULL;
    }

private:
    HANDLE         _mapFile;           // our Named Shared Memory handle
    ServerCommLink *_serverCommLinks;  // will point to shared memory, an array of size CEX_MAX_SERVER_COUNT
};
4

1 に答える 1