环形缓冲区

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

20.
return (i+1) == NMAX ? 0 : i+1;
21. }
22.
23.
/* 从环形缓冲区中取一个元素 */
24.
public double get() {
25.
int pos;
26.
if (n>0){
27.
pos = iget;
28.
iget = addring(iget);
29.
/* 向环形缓冲区中放人一个元素*/
39.
public void put(double z){
40.
if (n<NMAX){
41.
buffer[iput]=z;
42.
System.out.println("put<--"+buffer[iput]);
43.
iput = addring(iput);
44.
11.
12.
double buffer[]=new double[3];
13.
14.
/* 环形缓冲区的地址编号计算函数,,如果到达唤醒缓冲区的尾部,将绕回到头部。
15.
16.
环形缓冲区的有效地址编号为:0 到(NMAX-1)
17.
18. */
19.
public int addring (int i){
} 在 判 断 缓冲区是否满的条件中.之所以要摸maxlen, 是因为假设读写指针为 图1所示,
wptr所指的位置为空。为了区分缓冲区满和空两种情况的判定条件,此种情况 缓冲区被认为是已满。如果不采取模运算,wptr+l!=rptr,将认为可以继续写 数据,从而当写操作结束时,读写指针相等,会误认为队列空。该函 数 在 缓冲 区为满时返回FALSE;在队列有空位 置时写人一个数据元素.并返回TRUE. 2 并发条件下如何控制竞争 2.1 防止竞争的必要性 假设 写 任 务进行写操作时在语句mybuf->wptr++执行完时被打断,如图2 所示,此时写指针wptr所处的位置是非法的。当系统被切换到读任务时,如果 读任务有读多个数据的企图,那么不但应该读出的数据被读出来了,而且当读 指针被调整为0时、会将以前已读出的数据重复读出来。这种出错行为是由于写 指针的不正确位置所导致的。假设 读 任 务进行读操作在语句mybuf->rptr+十 执行完时被打断,如图3所示,此时读指针rptr所处的位置是非法的。当系统被 切换到写任务时,如果写任务有写多个数据的企图那么当写指针指向缓冲区的 末尾时,本来缓冲区应处于满状态,不应再写了。但由于读指针所处的非法位置 在读任务获得控制权之前,写任务认为缓冲区总是有空位置,将会租盖填写还 没有读出去的数据。
I 昊 群 .实时任务处理程序设计中“易变的’。变量.单片 机与嵌入式系统应用,2003 (4):77-78 2 La bro sseJe anJ. uc/OS-II一源码公开的实时嵌入式操 作系统.邵贝贝译.北京:中国电力出版社,2001 3 赵 克 佳,沈志宇等.UNIX程序设计教程.北京:清 华大学出版社,2001
实现代码:
1. package thread;
2.
3. public class CircularBuf {
4.
int NMAX=3;
5.
6.
int iput = 0; /* 环形缓冲区的当前放人位置 */
7.
8.
int iget = 0; /* 缓冲区的当前取出位置 */
9.
10.
int n = 0; /* 环形缓冲区中的元素总数量 */
环形缓冲区该写操作的分析与实现 环 形 缓 冲区是嵌人式系统中一种重要的常用数据结构.在多任务环境下实时, 如果有多个读写任务.一般需要用信号量来保护多个任务共享的环形缓冲区。但 是如果只存在1个读任务和1个写任务,采取适当的措施可以避免使用信号量, 从而提高程序的执行效率,并且避免任务间竟争所造成的不一致性。 1 单线程下的实现 先 定 义一 个简单的环形缓冲区数据结构;基于这样 一个条件,当环形缓冲区满时,不能再往里写数据了。 struct ringbuf{ uin t8 bu f[m axlen]; uin t8 r ptr ; uin t8 wp lr; 数据 元 素 是无符号8位整数,maxlen代表环形缓冲 区的最大长度,rptr为读指针,wptr为写指针。读写指 针初始化为rptr=wptr=0· 1.1 读操作的实现 BOOL readbuf(structringbuf "mybufuint8'readdata)I /队 列 为 空 if(m y bu f一>rptr= =m ybuf-> wptr) ret um F AL S E; els e[ 刀队 列 里 有 数 据,读出来 're ad dat a= rrty buf->buf[mybuf->印tr]; my bu f-> rp tr + +; /调 整 读 指 针 ,以防止读指针越界 my bu f-> rp tr- m ybuf->rptr./ m axlen; ret unr T R UE ; } } 该 函 数 在缓冲区为空时返回FALSE。在缓冲区有数据时,1次读1个敌据元素, 存放在readdata所指向的变量里,并返回TRUE. 2 写操作的实现 BOOL writebuf(structri ngbuf" mybufu int8w ritedata)] /队 列 为 满 if(m y bu f->rpt--=((mybuf->wptr+l)0lomaxlen)) ret unr F A LS E; els e] /队 列 有 空 位 置,写数据 my bu f-> bu f[m ybuf->wptr]=writedata; my bu f-> w ptr + +; /调 整 写 指 针 ,以防止写指针越界 my bu f-> wp tr- m ybuf->wptr%maxlen; ret ur nT R U E; }
n++;
45.
}else System.out.println("Buffer is full");
46. }
47.
48.
public static void main(String[] args){
49.
CircularBuf cb=new CircularBuf();
50.
cb.put(1);
51.
2.2 使用信号量 通过 上 述 分析可知,虽然读指针只由读任务来改写,写指针只由写任务来改 写;但是读任务要用到写指针,写任务要用到读指针,读写指针处于一个非法位 置时会给对方的判断造成错误。如果引人信号且机制,有效地保护临界区代码,
问题自然会得以避免。 2.3 改变读写指针的赎值方式 既 然 出 错都是由读写指针所处的非法位置引起的,那么修改读写指针时应注 意,不要赋非法位置。读写指针的值要么是还没有修改的要么是修改以后的正确 值,避免错误的值出现在读写指针中。另外还必须结合所使用的处理器,保证对 读写指针所定义的数据类型的赋值操作是原子性的。例如:如果所用处理器对16 位变量的赋值不是用一条指令实现的,需要分别对低字节和高字节进行操作那 么读写指针的数据类型就不能定义成16位的,或者说读写指针的使用范围应限 制在256以内。按照此种方法,假设处理器对8位变且的赋值是原子性的,读写 操作可以被改写为: BOOL readbuf(structri ngbuf* mybufu int8*re addata)I uin t8 t emp; /队 列为空 if(m y bu f一>rptr= =m ybuf一>wprt) ret unr F AL SE ; els e( /队 列 里 有 数 据,读出来 *er add at a=m y buf->buljmybuf->rprt); /j调 整 读 指 针 ,以防止读指针越界 tem p= m y bu f->rprt; tem p= ( tem p +l)0f omaxlen; my bu f-> 印 tr= temp; ret unr TR U E ; } } BOOL writebuf(structri ngbuf* mybufu int8w ritedata){ uin t8 t emp; /1队 列为满 if(m ybuf->rptr--((mybuf->wptr+l)%mmlen)) ret ur nF A LS E ; els e谭 /队 列 有 空 位 置,写数据 my bu f-> bu fjm ybuf->wprtl=writedata; /调 整 写 指 针 ,以防止写指针越界 tem p= m yb uf ->wprt; tem p= (t e m p+ 1)%maxlen; my bu f-> wp tr -temp; ert unr T R UE ; } } 引入 临 时 变量temp是为了进一步防范有些编译器在编译像temp=( temp+1)%maxlen这种语句时,在最终赋值变且前有可能修改变里的值。这 样,无论读写操作在何处被打断,都不会引起出错。班 参考 文 献
Leabharlann Baidu
cb.put(2);
52.
cb.put(3);
53.
cb.get();
54.
cb.put(4);
55.
cb.get();
56.
cb.get();
57.
cb.get();
58. }
59. }
n--;
30.
System.out.println("get-->"+buffer[pos]);
31.
return buffer[pos];
32.
33.
}else {
34.
System.out.println("Buffer is Empty");
35.
return 0.0;
36.
}
37. }
38.
相关文档
最新文档