3

私はもともと Visual C++ 6.0 で構築された古代の C++ アプリケーションを持っています。このアプリケーションは、非常に複雑な共有メモリ DLL を使用して、約 8 つの EXE と DLL の間でデータを共有しています。これらのすべての DLL は、1 つまたは 2 つの辞書で文字列に置き換えることができる値のプールを持っています。キー、および値のレコード。アプリケーションはマルチスレッドおよびマルチプロセスです。共有メモリ領域に読み書きする 3 つの主要な実行可能ファイルがあり、いくつかの実行可能ファイルには、このプールされたメモリ領域に情報を読み書きまたは「キュー」する 3 つ以上のスレッドがあります。__try約数百の場所で、 andの構造化例外処理 (SEH) を__except使用して例外をフィルタリングし、共有メモリのサイズを変更してアクセス違反を処理しようとします。CGMMFこれは、拡張可能なメモリ マップ ファイルを意味します。

使用されている技術、またはその安全性と適合性に関するドキュメントのまとまったソースが見つからないため、最も顕著な詳細をここに示します。実験的に、このライブラリは 1998 年のシングル コア システムではうまく動作しなかったことがわかりました。Windows XP を実行しているシングル コアの仮想マシンではある程度動作し、最近の 2+ GHz マルチではまったく動作しません。 -core Windows 7 64 ビット システム (2013 年)。修復または交換しようとしています。

#define ResAddrSpace(pvAddress, dwSize)  \
   (m_hFileMapRes = CreateFileMapping(HFILE_PAGEFILE, &m_SecAttr,             \
      PAGE_READWRITE| SEC_RESERVE, 0, dwSize, m_szRegionName),                    \
   (m_hFileMapRes == NULL) ? NULL :                                     \
      MapViewOfFileEx(m_hFileMapRes, FILE_MAP_ALL_ACCESS, 0, 0, dwSize, 0))


void CGmmf::Create(void)
{
    DWORD dwMaxRgnSize;
    if (Gsinf.dwAllocationGranularity == 0) 
    {
        GetSystemInfo(&Gsinf);
    }
    m_dwFileSizeMax = RoundUp(m_dwFileSizeMax, Gsinf.dwAllocationGranularity);
    m_dwFileGrowInc = RoundUp(m_dwFileGrowInc, Gsinf.dwAllocationGranularity);
    dwMaxRgnSize = m_dwFileSizeMax + m_dwOverrunBuf;
    m_pbFile = (PBYTE)ResAddrSpace(NULL, dwMaxRgnSize);
        Adjust(m_dwFileSizeNow);
}

void CGmmf::Adjust(IN DWORD dwDiskFileNow) 
{
    int nThreadPriority;

    __try 
    {
        //
        // Boost our thread's priority so that another thread is 
        // less likely to use the same address space while 
        //  we're changing it.
        //
        nThreadPriority = GetThreadPriority(GetCurrentThread());
        SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

        //
        // Restore the contents with the properly adjusted lengths
        //
        Construct(dwDiskFileNow);
    }
    __finally 
    {       
        //
        // Make sure that we always restore our priority class and thread 
        // priority so that we do not continue to adversely affect other 
        // threads in the system.
        //

        SetThreadPriority(GetCurrentThread(), nThreadPriority);
    }
}


void CGmmf::Construct(IN DWORD dwDiskFileNow) 
{
    DWORD dwDiskFileNew = RoundUp(dwDiskFileNow, m_dwFileGrowInc),
          dwStatus = ERROR_SUCCESS;

    PBYTE pbTemp;

    if (dwDiskFileNew > 0) 
    {
        //
        // Grow the MMF by creating a new file-mapping object.
        //
            // use VirtualAlloc() here to commit
        // the requested memory: VirtualAlloc will not fail
        // even if the memory block is already committed:

        pbTemp = (PBYTE)VirtualAlloc(m_pbFile,dwDiskFileNew,MEM_COMMIT,PAGE_READWRITE);

        if(NULL == pbTemp)
        {
            LogError(GetLastError(), MEM_CREATE_MMF, m_szRegionName);

            // 
            //  File-mapping could not be created, the disk is 
            //  probably full.
            //
            RaiseException(EXCEPTION_GMMF_DISKFULL, 
                           EXCEPTION_NONCONTINUABLE, 
                           0, 
                           NULL);
        }

        // 
        //  Check to see if our region has been corrupted 
        //  by another thread.
        //
        if (pbTemp != m_pbFile)
        {
            RaiseException(EXCEPTION_GMMF_CORRUPTEDRGN, 
                           EXCEPTION_NONCONTINUABLE, 
                           0, 
                           NULL);
        }
    }
}

これまでのところ、それを置き換えるための私のオプションには、すべての共有メモリをDCOM(プロセス外 COM) およびCOM(プロセス内 COM) に置き換えて、メモリがファイルをマップした場所に合わせて、同期を使用して手動で同時実行の問題を防ぐことが含まれます。 /mutex/criticalsection またはその他のスレッドセーフ構造を適宜変更します。

これをすべて置き換えることができるスレッドセーフなメモリ辞書タイプが既にあるかどうかを知りたいです。この古代のビジュアル C++-6 用共有メモリ ライブラリのコードの 1% 未満である上記のスニペットでさえ、私を身震いさせるものがあります。たとえば、デッドロック、競合状態、および一般的な破損を回避するための戦略として、スレッドの優先度を上げる。おそらく、このコードが 33 mhz の 80486 CPU でクラッシュするのをかなり止めていたのでしょう。身震い。

Visual C++ 6.0 でビルドして実行しているコードがあり、そのブランチも Visual C++ 2008 で実行されています。おそらく Visual C++ 2010 で実行できます。辞書のセマンティクス、プロセス間での共有メモリを提供するものを使用できます。 、そして安定して信頼できるものですか?

更新「ディクショナリ」とは、Python で知られているディクショナリ データ型を意味します。これは、ある場所では「キー/値ストア」とも呼ばれ、他の場所では (C++ 標準ライブラリのように) として知られていstd::mapます。これについて説明しているブーストのドキュメントはこちらです。

4

1 に答える 1

1

Boost Interprocessを見る必要があるようです。これを使用してstd::map、共有メモリなどに のようなオブジェクトを含めることができます。前回使用してから何年も経っているので、詳細を説明することはできませんが、ライブラリのドキュメントは優れており、たくさんの例があり、30 分で理解できるはずです。

于 2013-03-08T14:05:46.193 に答える