peakzhang 发表于 2008-4-29 09:53:20

共享内存文件的问题,是不是有什么限制?

在WIN32平台,我现在在作一个项目,用到了共享内存文件(ACE_Pagefile_Memory_Pool).想法是这样的:首先建立一个资源文件列表,参数为墨认.之后每有客户端在资源列表中添加一条信息,就建一个共享内存文件用于保存客户端程序发送来的数据,如果客户端程序长时间没有在对应的共享内存文件内写入数据,那就删除这个共享内存文件,并且把资源文件列表中的信息也一同删除.现在遇到几个问题:
1.共享内存文件的建立.测试要建至少20个共享内存文件用于保存客户端程序发来的数据,可是建立的时候出错,"unknown error",我想是不是ACE在共享内存文件建立上有限制啊,可是我找不到这方面的资料,有用过的前辈能否告诉我一些相关的信息.
2.多个定时器.我用多线程实现了多个REACTOR模式的定时器,可是一运行就出错,也定位不到代码,不过可能是我的代码写的不对,前辈能否指点一下.这个文件我问过了,可winston回答过于简单了,请说的再详细一些,我把相关的代码贴上来.

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static int worker(void *arg)
{ //工作线程函数
ACE_UNUSED_ARG(arg);
ACE_DEBUG((LM_DEBUG,
"Thread (%t) Created to do some work\n"));
CLogFileRes *ThreadParam = (CLogFileRes*)arg ;
// ACE_Process_Mutex ProMutex(ACE_TEXT("me"));
// ProMutex.acquire();
ACE_DEBUG ((LM_INFO,
ACE_TEXT ("(%t) worker hold \n")));
ACE_DEBUG((LM_DEBUG,
"id = %d\tbaseaddr = %ld file = %s start = %d\n",
ThreadParam->m_ui32id,
ThreadParam->m_ui32BaseAddr,
ThreadParam->m_pLogFile,
ThreadParam->m_bThreadStart));

//建立指定位置的共享区域
ALLOCATOR *pMemoryFile_allocator;
ACE_Pagefile_Memory_Pool_Optionsoptions((void *)(ThreadParam->m_ui32BaseAddr));
    TCHAR *name_ = ThreadParam->m_pLogFile;
ACE_NEW_RETURN (pMemoryFile_allocator,
ALLOCATOR (name_,name_,&options),-1);

//建立定时器定时扫描共享区
ACE_Time_Value interval(3);   
CFileSaveTimer_Handler
*pFileSave_Handler = new CFileSaveTimer_Handler(pMemoryFile_allocator,
                                                ThreadParam );

ACE_Reactor::instance ()->schedule_timer(pFileSave_Handler,0, interval, interval);

ACE_Reactor::instance ()->run_reactor_event_loop ();//--->>>>>>程序在这在出错了,弹窗
pMemoryFile_allocator->sync();

delete pMemoryFile_allocator;
pMemoryFile_allocator = 0;

delete ThreadParam;
ThreadParam = 0;
ACE_DEBUG ((LM_INFO,
ACE_TEXT ("(%t) worker exit\n")));
return 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//共享资源区定时扫描器类
class CFileResTimer_Handler : public ACE_Event_Handler
{
public:
CFileResTimer_Handler(HASH_MAP *hashmap):m_map(hashmap)
{
m_ui32max = 0;
};
int handle_timeout (const ACE_Time_Value &current_time,const void * = 0)
{
time_t epoch = ((timespec_t)current_time).tv_sec;
m_ui32max = static_cast<ACE_UINT32> (m_map->current_size ());
ACE_DEBUG ((LM_INFO,
   ACE_TEXT ("handle_timeout: %s    \n"), ACE_OS::ctime(&epoch));
//查找未建立线程标识的数据
//找到的话建立工作线程,把CLogFileRes当参数传给线程函数
ACE_Process_Mutex ProMutex(ACE_TEXT("me"));
ProMutex.acquire();
ACE_DEBUG ((LM_INFO,
   ACE_TEXT ("(%t) main hold ,main hold\n")));
int i = 0;
for (HASH_MAP::iterator iter = m_map->begin (); iter != m_map->end (); iter++)
{
   int key = (*iter) .ext_id_;

   CLogFileRes newRes ;
   int result = m_map->find (key, newRes, g_pFileRes);
   if (result == -1)
   {
    ACE_DEBUG ((LM_ERROR,
    ACE_TEXT ("Could not find record for %d\n"),
    key));
   }
   else
   {
    if (!newRes.m_bThreadStart)
    {
   //找到的话建立工作线程,把CLogFileRes当参数传给线程函数
   CLogFileRes newestRes = newRes;
   newestRes.m_bThreadStart = true;
   int newresult = m_map->rebind(key,newestRes,key,newRes,g_pFileRes);
   if (newresult == -1)
   {
      ProMutex.release();
      ACE_DEBUG ((LM_INFO,
       ACE_TEXT ("(%t) main no hold ,main no hold\n")));
      return 0;
   }
   //
   //传入线程的参数在线程退出之前不能空,否则线程内的参数就会为空会弹窗
   //解决办法:NEW一个参数传入线程,在退出线程时DELETE参数
   CLogFileRes *pThreadParam = new CLogFileRes(newRes);
   if(ACE_Thread::spawn((ACE_THR_FUNC)worker, (void*)pThreadParam) == -1)
   {
      ACE_DEBUG((LM_DEBUG,
       "Error in spawning threadRecord name: %d|addr:%d|file:%s|start = %d\n",
       newRes.m_ui32id,
       newRes.m_ui32BaseAddr,
       newRes.m_pLogFile,
       newRes.m_bThreadStart));
   }
    }
   }
}
ProMutex.release();
return 0;
}
private:
ACE_UINT32   m_ui32max;             //共享资源区的当前有用资源数
HASH_MAP       *m_map;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////
int ACE_TMAIN (int argc, ACE_TCHAR *[])
{
//建立日志文件资源内存共享文件
ACE_Pagefile_Memory_Pool_Options options;
    ACE_NEW_RETURN (g_pFileRes,
ALLOCATORROOT (MAP_NAME, MAP_NAME, &options),
-1);
//建立共享内存哈希表
    g_map = smap (g_pFileRes);
if (g_map == 0)
{
return 0;
}
addRecords(g_map, g_pFileRes);
ACE_Time_Value interval(1);    //扫描共享资源区的时间间隔1秒
CFileResTimer_Handler
*pFileResScan_Handler = new CFileResTimer_Handler(g_map);

ACE_Reactor::instance ()->schedule_timer(pFileResScan_Handler,
                                       0,
            interval,
            interval);

ACE_Reactor::instance ()->run_reactor_event_loop ();
g_pFileRes->sync ();

ACE_OS::system(ACE_TEXT("pause"));

g_map->close(g_pFileRes);

g_map = 0;
delete g_pFileRes;
g_pFileRes = 0;
delete pFileResScan_Handler;
pFileResScan_Handler = 0;
return 0;
}

这个代码是我通过ACE程序员指南里面的例子改的.各位前辈给点意见.

peakzhang 发表于 2008-4-29 09:53:34

代码编译不过去,缺少文件。
因为运行时的上下文的关系,需要调试才了解,毕竟程序是你写的。
说说我的想法:
1、加强调试的能力,推荐《Windows程序调试》一书,象此类bug,其实都是容易找到原因的类型,因为每次运行都出错。最难的是偶发类型的。
2、调试最基本的技巧只有几个,乐意与你分享:
   设置合适的断点,出错时候,看上下文堆栈,就能看到错误的来源
   看内存,就能看到对象的状态是否正确
如果无法进入ACE的模块内,说明你没有放置对应的调试信息符号文件在路径内,如*.pdb。
3、Reactor可以反复调用schedule_timer的,你可以跟踪一下代码,它对定时器支持的很好。

希望对你有所帮助。
页: [1]
查看完整版本: 共享内存文件的问题,是不是有什么限制?