c++共享内存问题

拜一刀 2015-12-02 05:08:05
接手了一个公司项目,wince7.0的,其中用到了共享内存,用的是http://blog.csdn.net/firehood_/article/details/6269310这里的共享内存代码.然后把,一个程序建立了共享内存,不停从下位机读数据写进共享内存里,另一边asp网页调用个dll也是同一套共享内存的东西来取数

现在问题是,取数这方面吧,每次都是open的新共享内存,然后就出了这么一个事:写数一方一直写的是同一个共享内存,然而某个时间点后会出问题.问题发生后,新open的同名共享内存都是空的读不到数,问题发生前open的共享内存还是能读到正常数据更新的

这个奇葩问题是出现在哪里,是不是网上那个共享内存有先天缺陷....我没搞过像样的c++,上班后玩vb.net了,对这方面不是很清楚,求指教.按我的想法实在不行就在写数据这边定期重新建立共享内存好了,不过比较担心内存泄露之类的orz

明早上班看回复单位电压低到160左右了,灯都打不开,蛋疼
...全文
585 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
拜一刀 2015-12-11
  • 打赏
  • 举报
回复
引用 19 楼 winnyrain 的回复:
[quote=引用 18 楼 zeratul1990 的回复:] [quote=引用 17 楼 winnyrain 的回复:] 正常,每次调用后映射来的内存地址可以不一样,但内容是一样的,改变这里面的内容,会改变全局的内容。
额,这样啊,那要判定映射来的东西有没有出问题的话,该看什么呢?有没有什么唯一的值,可以证明打开的确实是同一块内容呢? get last error的话得到的估计都是这个lpName的共享内存已经打开过的提示吧,明天我再继续试试[/quote] 你调用的那个类已经封装好了,Open的时候检查返回值1表示正常,0表示异常,2则表示创建过了直接ReadWrite。 另外在 Read的时候会返回TRUE或FALSE,是FALSE就代表没有内容了,不需要读取内容。[/quote] 哦哦哦,就是这,出问题的时候open会返回1,里面当然都是空的.我就加个timer来open下做个判断好了,返回1就把旧的关了重新建一个 拿到手的程序根本没判断返回值,怪不得一直找不到问题
拜一刀 2015-12-10
  • 打赏
  • 举报
回复
引用 13 楼 winnyrain 的回复:
你说每次OPEN,不需要 每次OPEN,只要初始化的时候OPEN一次。 使用的时候直接Read和Write。
写数据的一方是这样,open一次就好,读数据的一方是asp网页 用服务器端脚本调用dll取数,没办法,每次都得初始化,所以后来才出现了写数据一方写的地方没啥问题,自己可以读出来,asp读数据读的却是空数据 我正在试着把取得的句柄记录下来,看看能不能证实我的想法
Leckun 2015-12-10
  • 打赏
  • 举报
回复
你说每次OPEN,不需要 每次OPEN,只要初始化的时候OPEN一次。 使用的时候直接Read和Write。
Leckun 2015-12-10
  • 打赏
  • 举报
回复
那代码应该没什么大问题。应该是你使用上有问题。
Leckun 2015-12-10
  • 打赏
  • 举报
回复
引用 18 楼 zeratul1990 的回复:
[quote=引用 17 楼 winnyrain 的回复:] 正常,每次调用后映射来的内存地址可以不一样,但内容是一样的,改变这里面的内容,会改变全局的内容。
额,这样啊,那要判定映射来的东西有没有出问题的话,该看什么呢?有没有什么唯一的值,可以证明打开的确实是同一块内容呢? get last error的话得到的估计都是这个lpName的共享内存已经打开过的提示吧,明天我再继续试试[/quote] 你调用的那个类已经封装好了,Open的时候检查返回值1表示正常,0表示异常,2则表示创建过了直接ReadWrite。 另外在 Read的时候会返回TRUE或FALSE,是FALSE就代表没有内容了,不需要读取内容。
拜一刀 2015-12-10
  • 打赏
  • 举报
回复
引用 17 楼 winnyrain 的回复:
正常,每次调用后映射来的内存地址可以不一样,但内容是一样的,改变这里面的内容,会改变全局的内容。
额,这样啊,那要判定映射来的东西有没有出问题的话,该看什么呢?有没有什么唯一的值,可以证明打开的确实是同一块内容呢? get last error的话得到的估计都是这个lpName的共享内存已经打开过的提示吧,明天我再继续试试
Leckun 2015-12-10
  • 打赏
  • 举报
回复
引用 16 楼 zeratul1990 的回复:
[quote=引用 15 楼 winnyrain 的回复:] 我看了一下,重复调用初始化应该也没有影响,但是应该在下次再调用初始化时,调用Close,否则就会有内存泄漏。
多谢关照,每次用完之后都会调用close 我现在测试了下,每次用同一个lpName执行CreateFileMapping取得的句柄好像不一样,比如这次取得的是1F82B03,下次就是1F82C03,下下次就是1F82D03,这个正常么?[/quote] 正常,每次调用后映射来的内存地址可以不一样,但内容是一样的,改变这里面的内容,会改变全局的内容。
拜一刀 2015-12-10
  • 打赏
  • 举报
回复
引用 15 楼 winnyrain 的回复:
我看了一下,重复调用初始化应该也没有影响,但是应该在下次再调用初始化时,调用Close,否则就会有内存泄漏。
多谢关照,每次用完之后都会调用close 我现在测试了下,每次用同一个lpName执行CreateFileMapping取得的句柄好像不一样,比如这次取得的是1F82B03,下次就是1F82C03,下下次就是1F82D03,这个正常么?
Leckun 2015-12-10
  • 打赏
  • 举报
回复
引用 14 楼 zeratul1990 的回复:
[quote=引用 13 楼 winnyrain 的回复:] 你说每次OPEN,不需要 每次OPEN,只要初始化的时候OPEN一次。 使用的时候直接Read和Write。
写数据的一方是这样,open一次就好,读数据的一方是asp网页 用服务器端脚本调用dll取数,没办法,每次都得初始化,所以后来才出现了写数据一方写的地方没啥问题,自己可以读出来,asp读数据读的却是空数据 我正在试着把取得的句柄记录下来,看看能不能证实我的想法[/quote] 我看了一下,重复调用初始化应该也没有影响,但是应该在下次再调用初始化时,调用Close,否则就会有内存泄漏。
拜一刀 2015-12-04
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
两边都用create,怎么区分谁是The first producer?
研究了下,结果wince好像不支持open,我再看看
赵4老师 2015-12-04
  • 打赏
  • 举报
回复
The first producer creates the shared memory and sets up the queue. The remaining producers and consumers open the memory and immediately start using the existing queue. 两边都用create,怎么区分谁是The first producer? 你要想不区分谁是The first producer,那这还是producer/consumer问题吗? 莫非你实际遇到的是Single Instance问题? 解决Single Instance问题参考下面:
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "RECcap" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
    Test();
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif

    return 0;
}
拜一刀 2015-12-04
  • 打赏
  • 举报
回复
引用 2 楼 zhao4zhong1 的回复:
参考 Microsoft SDK\samples\winbase\SharedMem\*.*
您的例子里一边用的create,另一边用的open,我想问问如果两边都用create(按道理重名时会直接返回现有共享内存的句柄),会有可能出现同名的但不能相互访问的两组共享内存么?比如create时现有的A被锁住无法访问之类的,于是自行搞出个A',结果已经实例化A的还能继续访问A,新实例化时自动指向空白的A'了这样
拜一刀 2015-12-03
  • 打赏
  • 举报
回复
我去下个sdk看看,现在电脑里的没有sample...
拜一刀 2015-12-03
  • 打赏
  • 举报
回复
赵老师给力
赵4老师 2015-12-03
  • 打赏
  • 举报
回复
Microsoft SDK\samples\winbase\SharedMem\Queue.h
/*---------------------------------------------------------------------------
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright (C) 1999 - 2000 Microsoft Corporation.  All rights reserved.

queue.h

The queue is a ring buffer of N items.  The queue is a bounded size and cannot
grow.

Contents:
   QueueCreate        - Initializes a piece of memory into a queue
   QueueComputeSize   - Returns the size of the memory needed to hold a
                        queue of N items
   QueueAddItem       - Adds an item to the queue
   QueueRemoveItem    - Removes an item from the queue

Design notes:
   This queue interface is templatized so that the queue can take a variety
   of data types.

   Queues can reside in shared memory so they can be shared between processes.
   This implies they can be in multiple address spaces, and at a different base
   address in each process.  Therefore:

      1) This implementation uses an array-based implementation instead of a
         pointer implementation.

      2) This implementation does not use C++ objects.  The C++ compiler does
         not guarantee that entire objects will be placed entirely within the
         shared memory.  Specifically, vtables will not be.

   These queues are not reentrant and this implementation does not serialize
   access because enforcing any locking behavior may result in unnecessary
   overhead.  (i.e. when the queue is not shared, then no locking is needed)
   If these queues can be reentered (such as by multiple threads or processes),
   the calling code must provide synchronization tailored to its needs.
   Examples of such synchronization include mutexes, critical sections, or
   spin locks.
---------------------------------------------------------------------------*/

#if !defined (INC_QUEUE_H)
#define INC_QUEUE_H


#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <iostream>

template<class T> struct QUEUE
{
   int  nNumItems;    // 0
   int  nMaxItems;    // N items
   int  in;           // 0
   int  out;          // 0
   T    data[1];      // first element of queue data, full size will be N items
};


/*----------------------------------------------------------------------------
QueueCreate( pQueueBase, nNumQueueItems )

Creates a queue than can hold nNumQueueItems at once.  The caller must supply
the memory to hold the queue.  It is advised that the caller first call
QueueComputeSize to determine how much memory will be needed by the queue.

Parameters
   pQueueBase
      A pointer to memory that will contain the new queue.  This memory must
      be allocated by the caller.

   nNumQueueItems
      The maximum number of items that can be in the queue at any one time.

Return Value
   true if successfully created a queue, false if couldn't.

Notes
   This queue can be in shared memory.  It is not serialized so if multiple
   threads or processes can use the queue simultaneously, they need to
   synchronize access to the queue.
----------------------------------------------------------------------------*/
template<class T> bool QueueCreate (QUEUE<T> *pQueueBase, int nNumQueueItems)
{
   bool fResult;

   __try
   {
      pQueueBase->nNumItems = 0;
      pQueueBase->nMaxItems = nNumQueueItems;
      pQueueBase->in  = 0;
      pQueueBase->out = 0;

      fResult = true;
   }
   __except (EXCEPTION_EXECUTE_HANDLER)
   {
      fResult = false;
   }

   return fResult;
}


/*----------------------------------------------------------------------------
QueueComputeSize( pQueue, nNumQueueItems )

Computes the size in bytes of a queue that can hold nNumQueueItems.

Parameters
   pQueue
      Pointer of the queue to compute the size of.  Note that this pointer
      is not dereferenced, and does not need to point to allocated memory.
      It is used only to get the type (and therefore the size) of the items
      that will be stored in the queue.

   nNumQueueItems
      Maximum number of items to put into the queue.

Return Value
   The size in bytes of a queue that can hold nNumQueueItems.
----------------------------------------------------------------------------*/
template<class T> int QueueComputeSize (const QUEUE<T> *pQueue,
                                        int nNumQueueItems)
{
   return sizeof(QUEUE<T>) + ((nNumQueueItems-1) * sizeof(T));
}


/*----------------------------------------------------------------------------
QueueAddItem (pQueue, pItem )

Adds an item to the queue.  If the queue is full, this function returns
immediately (no waiting) without adding the item.

Parameters
   pQueue
      Pointer to the queue to which the item should be added.

   pItem
      Pointer to the item to add to the queue.

Return Value
   true if the item added to the queue, false if not.
----------------------------------------------------------------------------*/
template<class T> bool QueueAddItem (QUEUE<T> *pQueue, const T * pItem)
{
   // If the queue is full, return.
   if (pQueue->nNumItems == pQueue->nMaxItems)
      return false;

   /*
      Insert item, then advance in pointer to next empty slot, then update
      number of items in the queue.
   */
   pQueue->data[pQueue->in] = *pItem;
   pQueue->in = (pQueue->in +1) % pQueue->nMaxItems;
   ++pQueue->nNumItems;

   return true;
}


/*----------------------------------------------------------------------------
QueueRemoveItem( pQueue, pItem )

Removes an item from a queue.  If the queue is empty, this function returns
immediately.

Parameters
   pQueue
      Pointer to the queue from which the item should be removed.

   pItem
      Pointer to memory that will receive the item removed from the queue.

Return Value
   true if the item added to the queue, false if not.
----------------------------------------------------------------------------*/
template<class T> bool QueueRemoveItem (QUEUE<T> * pQueue, T * pItem)
{
   // if queue empty, return
   if (pQueue->nNumItems == 0)
      return false;

   // remove item, then advance out pointer to next item to remove
   *pItem = pQueue->data[pQueue->out];
   pQueue->out = (pQueue->out + 1) % pQueue->nMaxItems;
   --pQueue->nNumItems;

   return true;
}

#endif

Microsoft SDK\samples\winbase\SharedMem\Common.h
/*-------------------------------------------------------------------------
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright (C) 1999 - 2000 Microsoft Corporation.  All rights reserved.

common.h

Purpose
   Contains code that is common to both the producer and consumer.

Contents
   Names of shared kernel objects:

      FULL_SEM_NAME     -- semaphore to make producers sleep when queue full
      EMPTY_SEM_NAME    -- semaphore to make consumers sleep when queue empty
      QUEUE_LOCK_NAME   -- mutex to enforce exclusive access to queue

   Return values for main():
      SUCCESS
      FAILURE

-------------------------------------------------------------------------*/

#if !defined (INC_COMMON_H)
#define INC_COMMON_H

/* Names of kernel objects shared between producers and consumers */
#define FULL_SEM_NAME   "PC_FULL_SEM"
#define EMPTY_SEM_NAME  "EMPTY_FULL_SEM"
#define QUEUE_LOCK_NAME "PC_LOCK_MUTEX"


/* Return values for main() */
const int   SUCCESS = 0;
const int   FAILURE = 1;



#endif
赵4老师 2015-12-03
  • 打赏
  • 举报
回复
Microsoft SDK\samples\winbase\SharedMem\Consumer.Cpp
/*---------------------------------------------------------------------------
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright (C) 1999 - 2000 Microsoft Corporation.  All rights reserved.

consumer.cpp

Contents:
   The consumer process of the producer/consumer sample.  This sample shows
   how to use file mappings to implement a shared memory solution for the
   bounded-buffer producer/consumer problem.

Usage:
   To run this application, specify the shared memory name as a command-line
   parameter as follows:

      consumer memname

Design Notes:
   This sample allows any number of producers and consumers to access a
   single queue in shared memory.

   The first producer creates the shared memory and sets up the queue.  The
   remaining producers and consumers open the memory and immediately start
   using the existing queue.

   When the queue is full, producers will block until the queue has an
   open slot.  When the queue is empty, consumers will block until the queue
   has an item.  In order to prevent the producers and consumers from blocking
   forever, each waits with a timeout.  If the timeout occurs, the producer
   or consumer will check to see if the user wants to exit.  If not, they
   go back to waiting.

   To determine if a user wants to exit, a console control handler looks
   for a signal.  If one occurs, it sets a flag that the producer/consumer
   loop checks.

   Since the queue is not mutually exclusive, the producers and consumers
   share a single mutex to serialize access to the queue.

Notes:
   See QUEUE.H for queue implementation details.

   This sample will not compile for C; it requires C++ even though it does
   not use classes.

---------------------------------------------------------------------------*/

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <iostream>
#include "queue.h"
#include "common.h"



void ConsumeItem (int nItem);

BOOL WINAPI CtrlHandler (DWORD dwCtrlType);


bool g_fDone = false;

/*---------------------------------------------------------------------------
main (argc, argv)

Parameters
   argc
      Count of command-line arguments, including the name of the program.
   argv
      Array of pointers to strings that contain individual command-line
      arguments.

Returns
   SUCCESS if program executed successfully, FAILURE otherwise.
---------------------------------------------------------------------------*/
int main (int argc, char **argv)
{
   int   fResult = FAILURE;

   HANDLE       hMap           = 0;
   const char * pSharedMemName = 0;

   QUEUE<int> * pQueue;
   HANDLE       hFullSem   = 0,
                hEmptySem  = 0;
   HANDLE       hMutexLock = 0;

   int          item; /* used to hold data that's removed from queue */


   /*
      Validate command-line arguments. The last argument is the shared
      memory name.
   */
   if (argc != 2)
   {
      std::cerr << "usage: consumer <sharedmemname>\n";
      return FAILURE;
   }
   pSharedMemName = argv[argc-1];


   /*
      Open shared memory and producer/consumer synchronization objects.  If
      can't, exit.
   */
   hMap =  OpenFileMapping (FILE_MAP_WRITE, 0, pSharedMemName);
   if (!hMap)
      goto DONE;

   pQueue = (QUEUE<int> *)MapViewOfFile (hMap, FILE_MAP_WRITE, 0, 0, 0);
   if (!pQueue)
      goto DONE;

   hFullSem   = OpenSemaphore (SEMAPHORE_ALL_ACCESS, FALSE, FULL_SEM_NAME);
   hEmptySem  = OpenSemaphore (SEMAPHORE_ALL_ACCESS, FALSE, EMPTY_SEM_NAME);
   hMutexLock = OpenMutex (MUTEX_ALL_ACCESS, FALSE, QUEUE_LOCK_NAME);

   if (!hFullSem || !hEmptySem || !hMutexLock)
      goto DONE;


   /*
      Remove items from the queue and consume them until the user says stop.
      Use a console control handler to signal it's time to stop
   */
   SetConsoleCtrlHandler (CtrlHandler, TRUE);
   std::cerr << "Type Ctrl-C to exit\n";

   while (!g_fDone)
   {
      // if queue is empty and we time out, see if we should exit.
      if (WaitForSingleObject (hEmptySem, 1000) != WAIT_OBJECT_0)
         continue;

      WaitForSingleObject (hMutexLock, INFINITE);

      if (!QueueRemoveItem (pQueue, &item))
         std::cout << "couldn't remove item from queue!\n";

      ReleaseMutex (hMutexLock);
      ReleaseSemaphore (hFullSem, 1, 0);  // signal producer that queue has empty slot.

      ConsumeItem (item);
   }

   fResult = SUCCESS;

DONE:
   /* Clean up all opened resources before exiting. */

   if (!hFullSem)
      CloseHandle (hFullSem);

   if (!hEmptySem)
      CloseHandle (hEmptySem);

   if (!hMutexLock)
      CloseHandle (hMutexLock);

   if (pQueue)
      UnmapViewOfFile (pQueue);

   if (hMap)
      CloseHandle (hMap);

   if (fResult == FAILURE)
      printf ("couldn't share memory named %s\n", pSharedMemName);

   return (fResult);
}


/*---------------------------------------------------------------------------
ConsumeItem( nItem )

Consumes a single item by printing it to stdout.

Parameters
   nItem
      Item to be consumed.
---------------------------------------------------------------------------*/
void ConsumeItem (int nItem)
{
   std::cout << nItem << "\n";
}


/*---------------------------------------------------------------------------
CtrlHandler( dwCtrlType )

Captures the console control signals such as Ctrl+C or Ctrl+Break sent by
the user.  Then it signals the producer loop that the user would like to
exit.

Parameters
   dwCtrlType
      The console control signal that was generated.

Returns
   Always returns true because it handles all console control signals.
---------------------------------------------------------------------------*/
BOOL WINAPI CtrlHandler (DWORD dwCtrlType)
{
   /* For any event, signal producer loop that it's time to stop. */
   g_fDone = true;

   return TRUE;
}

赵4老师 2015-12-03
  • 打赏
  • 举报
回复
Microsoft SDK\samples\winbase\SharedMem\Producer.Cpp
/*---------------------------------------------------------------------------
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Copyright (C) 1999 - 2000 Microsoft Corporation.  All rights reserved.

producer.cpp

Contents:
   The producer process of the producer/consumer sample.  This sample shows
   how to use file mappings to implement a shared memory solution for the
   bounded-buffer producer/consumer problem.

Usage:
   To run this application, specify the shared memory name as a command-line
   parameter as follows:

      producer memname


Design Notes:
   This sample allows any number of producers and consumers to access a
   single queue in shared memory.

   The first producer creates the shared memory and sets up the queue.  The
   remaining producers and consumers open the memory and immediately start
   using the existing queue.

   When the queue is full, producers will block until the queue has an
   open slot.  When the queue is empty, consumers will block until the queue
   has an item.  In order to prevent the producers and consumers from blocking
   forever, each waits with a timeout.  If the timeout occurs, the producer
   or consumer will check to see if the user wants to exit.  If not, they
   go back to waiting.

   To determine if a user wants to exit, a console control handler looks
   for a signal.  If one occurs, it sets a flag that the producer/consumer
   loop checks.

   Since the queue is not mutually exclusive, the producers and consumers
   share a single mutex to serialize access to the queue.

Notes:
   See QUEUE.H for queue implementation details.

   This sample will not compile for C; it requires C++ even though it does
   not use classes.
---------------------------------------------------------------------------*/

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <iostream>
#include "queue.h"
#include "common.h"


const int MAX_QUEUE_ITEMS = 50;

int ProduceItem (void);
BOOL WINAPI CtrlHandler (DWORD dwCtrlType);


bool g_fDone = false;


/*---------------------------------------------------------------------------
main (argc, argv)

The main program that implements the producer process of the producer/consumer
sample.

Parameters
   argc
      Count of command-line arguments, including the name of the program.
   argv
      Array of pointers to strings that contain individual command-line
      arguments.

Returns
   SUCCESS if program executed successfully, FAILURE otherwise.
---------------------------------------------------------------------------*/
int main (int argc, char **argv)
{
   int          fResult     = FAILURE;
   DWORD        dwMapResult;

   HANDLE       hMap           = 0;
   const char * pSharedMemName = 0;

   QUEUE<int> * pQueue     = 0;
   HANDLE       hFullSem   = 0,
                hEmptySem  = 0;
   HANDLE       hMutexLock = 0;

   int          item;  /* used to hold data that's put into the queue */

   /*
      Validate command-line arguments. The last argument is the shared
      memory name.
   */
   if (argc != 2)
   {
      std::cerr << "usage: producer <sharedmemname>\n";
      return FAILURE;
   }
   pSharedMemName = argv[argc-1];


   /*
      If the shared memory is not already created, create it and set up the
      queue. If the shared memory already exists, skip making the queue.

      Then, create or open the synchronization objects associated with the
      queue that are needed for an efficient solution to the producer/consumer
      with bounded buffer problem.  The initial state of producer/consumer
      synchronization objects must be:

         full semaphore count:   N for an N-item queue
         empty semaphore count:  0
         lock mutex:             unowned
   */
   hMap =  CreateFileMapping (INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0,
                              QueueComputeSize (pQueue, MAX_QUEUE_ITEMS),
                              pSharedMemName);
   dwMapResult = GetLastError();
   if (!hMap)
      goto DONE;

   pQueue = (QUEUE<int> *)MapViewOfFile (hMap, FILE_MAP_WRITE, 0, 0, 0);
   if (!pQueue)
      goto DONE;

   if (dwMapResult != ERROR_ALREADY_EXISTS)
      if (!QueueCreate (pQueue, MAX_QUEUE_ITEMS))
         goto DONE;

   hMutexLock = CreateMutex (NULL, FALSE, QUEUE_LOCK_NAME);
   hFullSem   = CreateSemaphore (NULL, pQueue->nMaxItems, pQueue->nMaxItems,
                                 FULL_SEM_NAME);
   hEmptySem  = CreateSemaphore (NULL, 0, pQueue->nMaxItems, EMPTY_SEM_NAME);
   if (!hFullSem || !hEmptySem || !hMutexLock)
      goto DONE;


   /*
      Produce items and add them to the queue until the user says stop.
      Use a console control handler to signal it's time to stop
   */
   SetConsoleCtrlHandler (CtrlHandler, TRUE);
   std::cerr << "Type Ctrl-C to exit\n";

   item = ProduceItem();

   while (!g_fDone)
   {
      // if queue is full and we time out, see if we should exit.
      if (WaitForSingleObject (hFullSem, 1000) != WAIT_OBJECT_0)
         continue;

      WaitForSingleObject (hMutexLock, INFINITE);

      QueueAddItem (pQueue, &item);

      ReleaseMutex (hMutexLock);

      ReleaseSemaphore (hEmptySem, 1, 0);  // signal consumer--queue not empty

      std::cout << item << "\n";   // print item just added but not inside lock
      item = ProduceItem();        // make next item
   }

   fResult = SUCCESS;

DONE:
   /* Clean up all opened resources before exiting. */

   if (!hFullSem)
      CloseHandle (hFullSem);

   if (!hEmptySem)
      CloseHandle (hEmptySem);

   if (!hMutexLock)
      CloseHandle (hMutexLock);

   if (pQueue)
      UnmapViewOfFile (pQueue);

   if (hMap)
      CloseHandle (hMap);

   if (fResult == FAILURE)
      std::cout << "couldn't share memory named " << pSharedMemName << "\n";

   return (fResult);
}


/*---------------------------------------------------------------------------
ProduceItem( )

Produces a single item.

Returns
   A new item.
---------------------------------------------------------------------------*/
int ProduceItem (void)
{
   int item;

   item = (int)GetCurrentProcessId();
   return (item);
}


/*---------------------------------------------------------------------------
CtrlHandler( dwCtrlType )

Captures the console control signals such as Ctrl+C or Ctrl+Break sent by
the user.  Then it signals the producer loop that the user would like to
exit.

Parameters
   dwCtrlType
      The console control signal that was generated.

Returns
   Always returns true because it handles all console control signals.
---------------------------------------------------------------------------*/
BOOL WINAPI CtrlHandler (DWORD dwCtrlType)
{
   /* For any event, signal producer loop that it's time to stop. */
   g_fDone = true;

   return TRUE;
}

拜一刀 2015-12-03
  • 打赏
  • 举报
回复
引用 2 楼 zhao4zhong1 的回复:
参考 Microsoft SDK\samples\winbase\SharedMem\*.*
赵四老师~有可用的下载没,我下载了个v6.0的sdk,但是winbase里面没有sharedmem,微软那边一进去就什么win10啊win phone的sdk
赵4老师 2015-12-02
  • 打赏
  • 举报
回复
参考 Microsoft SDK\samples\winbase\SharedMem\*.*
拜一刀 2015-12-02
  • 打赏
  • 举报
回复
晚上研究研究厂家例子去

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧