【发布时间】:2016-01-04 12:29:21
【问题描述】:
我有一个使用文件映射 (slides 8-9) 进行 IPC 的旧代码。但是当通过通道进行高负载读写时,写入器线程会挂在MapViewOfFile上。 MSDN 没有关于MapViewOfFile 的阻塞行为的信息。可能的原因是什么?
虽然整个源代码可能是found on github,但代码的相关部分是
BOOL Channel::Read(LPVOID data, DWORD dataSize, BOOL response/* = FALSE*/)
{
::WaitForSingleObject(m_events[response
? RESPONSE_AVAILABLE
: REQUEST_AVAILABLE],
INFINITE);
LPVOID source = ::MapViewOfFile(m_section, FILE_MAP_ALL_ACCESS, 0, 0, dataSize);
if (!source) {
if (!response) {
::SetEvent(m_events[SERVER_AVAILABLE]);
}
return FALSE;
}
::CopyMemory(data, source, dataSize);
BOOL ok = ::UnmapViewOfFile(source);
if (!response) {
::SetEvent(m_events[SERVER_AVAILABLE]);
}
return ok;
}
BOOL Channel::Write(LPVOID data, DWORD dataSize, BOOL response/* = FALSE*/)
{
if (!response) {
::WaitForSingleObject(m_events[SERVER_AVAILABLE], INFINITE);
}
LPVOID destination = ::MapViewOfFile(m_section, FILE_MAP_ALL_ACCESS, 0, 0, dataSize);
if (!destination) {
if(!response) {
::SetEvent(m_events[SERVER_AVAILABLE]);
}
return FALSE;
}
::CopyMemory(destination, data, dataSize);
if (::UnmapViewOfFile(destination)) {
::SetEvent(m_events[response
? RESPONSE_AVAILABLE
: REQUEST_AVAILABLE]);
return TRUE;
} else {
::SetEvent(m_events[(response
? RESPONSE_AVAILABLE
: SERVER_AVAILABLE)]);
return FALSE;
}
}
【问题讨论】:
-
如果对
MapViewOfFile的调用无限期挂起,您可以创建转储文件(例如使用任务管理器)以供以后分析。然后可以使用 WinDbg 的 !locks 命令来识别正在等待的同步对象。 -
太丑了,扔掉它,改用命名管道。
-
@HansPassant 可能是我听过的最好的推荐。我很想扔掉 OpenForge 的全部源代码(Aviro 杀毒软件甚至将其后代检测为危险应用程序)。
-
一个可能的原因是交换 - 如果内存不足,MapViewOfFile 将交换出内存。您确定在此期间您有足够的物理内存吗?
-
@SergeyA 看起来就是这样。问题很可能出现在 QA 的 VM 上,而不是开发人员机器上。明天我会进一步检查。你会这么好心把这个作为答案发布吗? :)
标签: c++ multithreading winapi ipc