4939|22

66

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

怎么处理多进程共享内存的耦合性问题?? 送分 [复制链接]

最近遇到个多进程共享内存的同步问题,困扰了好几天(由于不想用Mute等来加锁,所以准备自己写一个简单:(
下面是我的设计思路,请朋友们帮忙看看,指点一下,呵呵


一、以下是共享内存区域的数据结构体定义:
Struct
{
   int len;
   BYTE buffer[200];
}DATA;

Struct
{
   volatile int count;
   int  sum;
   int  frep;
   DATA buf;
   BOOL bIsPowerOff;
}SHARE_INFO;

SHARE_INFO *shareInfo;

二、环境
有A、B两个进程可能同时对shareInfo进行访问,各自在初始化时都会加载(CreateFileMapping..)共享内存区域.


二、设计思路
读操作:
A(B)在读取shareInfo内容前,先读取count值,如果为-1(-1表示正在写),则进入超时等待状态,否则表示共享内存可读,执行读操作:
count =1; //表示开始读数据
读取共享内存中的数据;
count =0; //表示读数据完成

写操作:
A(B)在写shareInfo前,先读取count值,如果为非0(0表示内存空闲),则进入超时等待状态,否则执行写操作:
count =-1; //表示开始写数据
更新共享内存中的数据;
count =0; //表示写数据完成

以这样的思路来达到对共享内存的同步访问,请问是否正确??

最新回复

InterLocked函数似乎没有停等的功能,我写了下面函数来实现如果共享产生竞争,则进入超时模式来等待重新访问共享数据 void WriteLock() {     if( InterLockedCompareExchange(count,-1,0) != -1 )     {        //Lock request false, access timeout mode and continue to request..        int i=3;        for( i;i>0;i-- )        {           Sleep(0);           if( InterLockedCompareExchange(count,-1,0) == -1 )           {              break;           }        }     } } void WriteUnLock() {    if( InterLockedCompareExchange(count,0,-1) != 0 )     {        //Unlock request false, access timeout mode and continue to request..        int i=3;        for( i;i>0;i-- )        {           Sleep(0);           if( InterLockedCompareExchange(count,0,-1) == 0 )           {              break;           }        }        //timeout and give up     } } main() {     WriteLock();     DataCopy();     WriteUnLock(); } 以这样的方式来做,不知是否可行??  详情 回复 发表于 2009-4-15 10:17
点赞 关注

回复
举报

61

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
设置临界区,用系统提供的比较安全
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
同意楼上;
楼主考虑一个问题:(假设)
A,B进程都没有开始进行操作,你的count貌似为0;
假设当A进程开始进行写操作时,在他判读count为0,准备写时,系统有中断发生,此时系统调度,到B进程运行,假设B此时也要进行操作,他也判断count,发现count为0,他也开始写;

A的操作岂不是又问题了?

最起码给count加个锁吧
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

4
 
楼上说的有道理!
不过,因为这块内存访问的频率会非常高,效率问题就比较重要,所以不想用Mute这类需要内核模式切换的操作.
现在的问题是有可能process A(B)在if(count)和count=-1中间被中断而引发的同步问题,有没有解决方法?
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

5
 
系统都有了还自己来写
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

6
 
比如这样:
if( count ==0 )  //当前内存空闲
Sleep(0);         //先放弃本次CPU时间片
if( count ==0 )         //再CHECK一下标志
{
   //此时认为读写操作可靠
   //操作
}

感觉有点邪门歪道,呵呵
有没有其它标准非主流的方法阿,谢谢~
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

7
 
还是用体系提供的 mutex 更安全可靠一些...
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

8
 
引用 5 楼 nomad1982 的回复:
比如这样:
if( count ==0 )  //当前内存空闲
Sleep(0); //先放弃本次CPU时间片
if( count ==0 ) //再CHECK一下标志
{
  //此时认为读写操作可靠
  //操作
}

感觉有点邪门歪道,呵呵
有没有其它标准非主流的方法阿,谢谢~

这样还是一样的啊,就算你sleep了一段时间,但是还是没法保证第二次count操作时,系统调度的发生。。。
 
 
 

回复

89

帖子

0

TA的资源

一粒金砂(初级)

9
 
因为AB进程中的线程优先级是一样的,不考虑A(B)发生与系统高优先级反转的可能,AB中的线程应该是CPU时间片轮转的,再说:在我的系统中没有那么复杂的多任务多线程环境,所以个人觉得在A使用SLEEP(0)放弃当前时间片后的再获得下一个时间片的一段时间(暂且叫一段时间)内是不会发生B进程抢占/调度的(其他系统任务进程、线程,因为跟共享内存无关,所以不考虑),所以这样的做法我认为在某种场合下应该是可行的,不知道是不是这样?
另外,可以考虑做个测试,看看在实际系统中的运行情况~~
呵呵
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

10
 
学习了
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

11
 
应该考虑用临界区资源的方法
 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

12
 
其实系统的这些函数,最后也是对变量的赋值,没有什么复杂的。

效率问题只是LZ主观认为的吧!!!
 
 
 

回复

81

帖子

0

TA的资源

一粒金砂(初级)

13
 
好问题,关注啊!
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

14
 
Windows CE开放了EnterCriticalSection()函数的源代码,LZ可以去学习学习
 
 
 

回复

60

帖子

0

TA的资源

一粒金砂(初级)

15
 
引用 11 楼 91program 的回复:
其实系统的这些函数,最后也是对变量的赋值,没有什么复杂的。

效率问题只是LZ主观认为的吧!!!


如果是同一进程之内的线程同步问题,我想我会毫不考虑的用临界区,就像你说的一样
但是进程之间的同步需要用Mutex等内核对象来完成同步,需要进行系统运行模式切换,比较损耗效率
打个不是很准确的比方:
两辆正在飙车的车子(非比赛,也不考虑会被交警扣留)刚好在同一时刻到达单行桥,那么让谁先通过呢?
标准做法:
都停下来,等交警来指挥,然后排队后继续上路

而我的想法是想在不通过交警的协助下,两个人怎样合理有效的通过来节省时间.

回到我的问题上,有个疑问:
假如按照设计AB都会遵守规则,当A从Sleep(0)中恢复过来时,刚准备设置count =-1;
确被更高优先级的C阻塞了,那我想问的是等C释放CPU后,系统是不是应该先恢复运行A,在轮转到B??
如果不是这样,而是一旦A被阻塞就需要排队到B后面,可能就是出现问题了!
 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(初级)

16
 
你是指A的优先级大于B?如果大的话,就不用sleep了,B不会打断A的操作的,但是B的操作会被A打断,使B的操作出现问题;
如果A,B同优先级的话,就算sleep也还是会出现问题的,因为在sleep后,在A操作count前,没有人会保证没有中断发生(不是原子操作),假若此时系统时间片到,换下一个进程B,还是会出错的;除非你关中断
 
 
 

回复

53

帖子

0

TA的资源

一粒金砂(初级)

17
 
你没明白我的意思,呵呵
 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(初级)

18
 
A,B同优先级
if( count ==0 )          //当前内存空闲
Sleep(0);                 //先放弃本次CPU时间片
if( count ==0 )         //这时线程再次获得CPU,如果不考虑高优先级抢占的情况,A是可以运行一个时间片的,而这个时间片足够A来完成count =-1的指                         //令了,所以不可能存在A刚获得时间片,B又开始运行的情况 ,如果考虑高优先级的话,就回到我提到的问题,系统调度机制上了.
{
  //此时认为读写操作可靠
  //操作
}
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

19
 
你可以用Interlocked API来访问count。
 
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

20
 
是的,可是这样还是无法保证共享内存中的其它数据能够同步访问!
关于我上面提到的问题

“假如按照设计AB都会遵守规则,当A从Sleep(0)中恢复过来时,刚准备设置count =-1;
确被更高优先级的C阻塞了,那我想问的是等C释放CPU后,系统是不是应该先恢复运行A,在轮转到B??
如果不是这样,而是一旦A被阻塞就需要排队到B后面,可能就是出现问题了!”

我查了下线程调度的机制,
所有线程从运行态转换到其它态最终都需要进入就绪态下重新按照调度策略来执行,也就是说无法保证A,B的运行顺序了,所以我的想法估计要无疾而终了。 哎~~
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表