关于共享内存互斥的问题,请高手来指教一下
我自己写了一个类,就是创建一个共享内存,然后实现进程之间共享数据,比如A进程就是往内存里写入数据,B进程就是从内存里读取数据,当然这是需要加锁互斥的,我自己也写了一个锁,但是锁偶尔会出问题:
例如:A进程依次往内存里写入ABCDEFG,正常情况B读出也是ABCDEFG, 但是却会出现ABCCEFG这样的情况,请各位大侠指教一下
上代码
m_lpFileMapBuffer = MapViewOfFile(m_hFileMap, dwAccess, 0, 0, dwSize);
LPVOID ShareMemory::GetBuffer()
{
return (m_lpFileMapBuffer)?(m_lpFileMapBuffer):(NULL);
}
void ShareMemory::Lock()
{
while ( InterlockedExchange(&m_lock, RESOURCE_IN_USE) == RESOURCE_IN_USE )
Sleep(1);
}
void ShareMemory::Unlock()
{
InterlockedExchange(&m_lock, RESOURCE_IN_FREE);
}
BOOL ShareMemory::WriteData(char *pData, DWORD dwSize)
{
Lock();
BOOL ret = FALSE;
char *p = (char *)GetBuffer();
if (p)
{
memcpy(p, (char*)&pData, dwSize);
ret = TRUE;
}
Unlock();
return ret;
}
BOOL ShareMemory::ReadData(char* &pData, DWORD dwSize)
{
Lock();
BOOL ret = FALSE;
char *p = (char *)GetBuffer();
if (p)
{
p = pData;
ret = TRUE;
}
Unlock();
return ret;
}
[解决办法]
1。同一段物理地址,不同进程映射的虚拟地址都不一样,同时也都不等于物理地址的值。如果一样,那恰好只是因为调试器给你分配的一样。建议你在win7中调试,程序启动后每次的基地址都不同,这样更便于你发现问题。
2。从你的描述看,你要的是指针指向的内容,而不是指针值本身。那么你就应该在枷锁期间把指针指向的内容从本地内存拷贝到共享区(就像你WriteData函数那样)和从共享区拷贝到本地内存(你的ReadData只考了个指针)。一旦你离开了加锁区间,内容就有可能改变。所以光拷贝指针是无效的。
[解决办法]
共享内存共享的是地址的内容,而不是地址的值
[解决办法]
大哥,什么叫做“完全独立”呢?
这与是否是一个类没有任何关系。
这么说吧,你知道我们的程序最终其实都是调用系统的api函数的,那么这些函数其实都是在系统自带的dll里面的。
那么,为什么那么多的程序调用同一个dll,居然不会有数据冲突呢?
就是因为所有的程序的内存空间都是完全独立的。即使是同一个dll,不同的程序调用的时候,数据的内存地址也是不同的。
同样了,不同进程本身也是一样。
同一个类只代表生成的代码是一样的,而没有其他更多的含义。
[解决办法]
MapViewOfFile得到同一个m_hFileMap的lpFileMapBuffer的值(这个值是用户模式内存指针的值),不同进程的都不一样的。但是指向的物理地址和内容都一样
[解决办法]
用内存映射文件啊,
何必搞这么复杂?
[解决办法]
你把函数ReadData改一下吧,改成类似WriteData那样的:
BOOL ShareMemory::WriteData(const char *pData, DWORD dwSize)
{
Lock();
BOOL ret = FALSE;
char *p = (char *)GetBuffer();
if (p)
{
memcpy(p, pData, dwSize);
ret = TRUE;
}
Unlock();
return ret;
}
BOOL ShareMemory::ReadData(char* pData, DWORD dwSize)
{
Lock();
BOOL ret = FALSE;
char *p = (char *)GetBuffer();
if (p)
{
memcpy(pData, p, dwSize);
ret = TRUE;
}
Unlock();
return ret;
}
ReadData要用自己申请的内存,不要用个空指针或未定义指针传进去了。
[解决办法]
他用的就是内存映射文件,没看到吗??
[解决办法]
m_lock是啥
[解决办法]
m_lock也应该搞成在进程间共享。不然形同虚设了...
[解决办法]
#pragma data_seg("Shared")
volatile LONG m_lock = RESOURCE_IN_FREE;
#pragma data_seg()
#pragma comment(linker, "/Section:Shared,rws")
[解决办法]
m_lock也要通过filemap共享
看这个 blog.csdn.net/lactoferrin/article/details/7316067
[解决办法]
看来你还是只保护了指针。你清楚锁真正的作用吧:其实就只是防止两个不同的线程(进程内的不同线程或两个进程之间)同时执行锁区间的代码。仅此而已。你给指针加了个锁就觉得可以保护指针指向的内容了吗?不是的。你自己可以想像一下:代码在锁区间内并没有同时执行的问题(每次确实只有一个线程在执行锁区间内的代码)。假设某时段中当读线程离开锁区间以后,该线程又去访问指针指向的内容。这时候如果写线程开始进入锁区间内并执行自己的代码了,就会出现读线程取出的数据被写线程改写的情况
[解决办法]
1。你要在锁区间内部做完所有不能同时操作的事情后,才能离开锁区间。
2。指针不能在进程间传递。不然的话在一个进程得到的指针指向一片内容,传到另一个进程中会指向不知道什么地方去了。
3。MapViewOfFile返回的指针,虽然指向的内容是一样的,但每个进程调用他得到的指针只能该进程自己用。如果有两个进程得到的指针值一样,那也只是巧合(概率还比较大...)。指针是不会共享的
[解决办法]
汗...
你的WriteData目前看来没问题
有问题的是ReadData...
[解决办法]
lock函数就实现错了
[解决办法]
方便的话提供一个你简化过的测试代码
[解决办法]
微软msdn 的 内存映射文件的IPC示范 代码,多么简洁实用
何必搞得那么多包装来包装去没多大意义的类...
赵老湿:能用C语言写xx行的代码,千万不要用c++改写
[解决办法]
while(InterlockedCompareExchange(&lock,1,0)!=0)Sleep(0);
[解决办法]
难得见你回帖