最近我在学习操作系统这本书。操作系统实现了应用程序和硬件的连接,属于硬件和用户程序之间的接口。对资源的管理和对进程的调度执行是操作系统的核心。为了解决IO设备的存取速度和CPU对数据处理速度的不匹配的问题,设计师引入了缓冲区这一个概念。将IO的数据先存放在缓冲池,存放到一定数目时将其传入内存交由CPU进行处理。所以我想用java语言来简要实现一下我个人对环形缓冲区的理解。
首先我想简要介绍一下什么是环形缓冲池。顾名思义,就是由若干个缓冲池组成的一个循环队列。数据可以放入这些缓冲器或者从里面取出,然后再将数据放入空的缓冲区中。为了方便我们的使用和管理,在此引入了三个指针。
public Integer nextg;//下一个可用的缓冲区,即其中的数据可以被进程使用
public Integer nexti;//下一个空的缓冲区
public Integer current;//当前正在使用的缓冲区
缓冲区中我也设置了一个属性,用来表示该缓冲区的情况。
/**
* 设置该缓冲区的状态.0表示为空。1表示包含数据可以被操作.2表示正在数据被进程使用
*/
public Integer status = 0;
当然我们还需要三个功能。一个是实现数据传入缓冲区,另一个是将数据从缓冲区中取出来交给进程进行处理,还有一个就是清空缓冲区。
下面我想对我的算法进行一个简要的解释。
首先使用一个有参构造函数,入参为缓冲区的个数,将nextg和nexti的值设为0,将current的值设为null。
下面我来介绍我的将数据传入缓冲区的函数。putBuf(Object o),其中的入参为传入该缓冲区的内容。传入一个数据后,确认nexti的值,如果为null,则令它等于nextg的值。因为这说明在传入该数据之前,这个环形缓冲区没有数据(这是我的算法的设定)。之后nextg进行遍历找到下一个空的缓冲区,并更改指针值。
然后是getBuf(),这个函数是从nexti指向的缓冲区中进行取值,然后让current的值指向nexti。修改缓冲区的status属性为2,表示正在使用中。待数据处理完之后,调用releaseBuf(Integer current)函数。
关于releaseBuf(Integer current)函数,这个构思很简单。只有三行代码。
this.mbArray[current].data =null;
this.mbArray[current].status = 0;
this.nexti = this.current;//当前缓冲区设置为下一个可以使用的空缓冲区
下面是我的算法的完整代码
由于是第一次,可能会有一些问题,欢迎大家指正。
package com.xt.myos.iotest.bufferingpool.test;
import com.xt.myos.iotest.bufferingpool.util.MyBuffer;
public class MyCircleBuffer {
public Integer nextg;//下一个可用的缓冲区,即其中的数据可以被进程使用
public Integer nexti;//下一个空的缓冲区
public Integer current;//当前正在使用的缓冲区
public int maxsize;//缓冲区的个数
public MyBuffer[] mbArray;
public MyCircleBuffer(int maxsize) {
super();
mbArray = new MyBuffer[maxsize];//将缓冲区初始化
for(int i=0;i<maxsize;i++){
MyBuffer mb = new MyBuffer();
mb.rank = i;
mb.data=null;
mbArray[i] = mb;
}
this.maxsize = maxsize;
this.current=null;
this.nexti=0;
this.nextg = 0;//
}
/**
* 选取下一个空缓冲区存放内容
* @throws Exception
*/
public boolean putBuf(Object o) throws Exception{
if(this.nexti==null){
throw new Exception("所有缓冲区已满,不能在存放数据");
}
mbArray[this.nexti].data = o;//存放的内容
mbArray[this.nexti].status = 1;//将该缓冲区修改成当前的数据可以被访问
//如果nextg的值为null,说明在放入该数据之前原缓冲区数组为空,将执行this.nexti = this.nextg
if(this.nextg==null){
this.nextg = this.nexti;
}
//从该空缓冲区向后检索,直到发现第一个空缓冲区退出该函数
for(int i=this.nexti;i<this.maxsize;i++){
if(mbArray[i].status==0){
this.nexti = i;
return true;
}
}
//如果该缓冲区向后无缓冲区,则从缓冲区数组最开始进行检索
for(int i=0;i<this.nexti;i++){
if(mbArray[i].status==0){
this.nexti = i;
return true;
}
}
this.nexti = null;
return false;
}
/**
* 从nexti指向的缓冲区中获取数据
* @return
* @throws Exception
*/
public boolean getBuf() throws Exception{
if(this.nextg==null){
throw new Exception("没有可以获取数据的缓冲区,内容获取失败");
}
if(this.mbArray[this.nextg].data==null){
throw new Exception("该缓冲区没有内容,内容获取失败");
}
this.mbArray[this.nextg].status = 2;//要提取该缓冲区的数据时,将该缓冲区的状态设置为2
this.current = this.nextg;//让当前工作的缓存指针指向nexti
System.out.println("现在将 "+this.mbArray[this.current].rank+"号缓冲区内的内容: "+this.mbArray[this.nexti].data+"交给进程进行处理");
System.out.println("当前正在提取数据的缓冲区是: "+this.mbArray[this.current].rank);
releaseBuf(this.current);
for(int i=this.nextg;i<this.maxsize;i++){
if(mbArray[i].status==1){
this.nextg = i;
return true;
}
}
for(int i=0;i<this.nextg;i++){
if(mbArray[i].status==1){
this.nextg = i;
return true;
}
}
this.nextg=null;
return false;
}
/**
* 将指定的缓冲区的内容设置为null
* @param current
* @return
*/
public boolean releaseBuf(Integer current){
this.mbArray[current].data =null;
this.mbArray[current].status = 0;
this.nexti = this.current;//当前缓冲区设置为下一个可以使用的空缓冲区
return true;
}
@Override
public String toString() {
return "下一个可用缓冲区G是: "+nextg+" \n"
+"下次可用的空缓冲区R是: "+nexti+" \n"
+"指示计算进程正在使用的缓冲区C的指针: "+current;
}
}