minix块高速缓存的模拟实现

来源:互联网 发布:小米手环2无睡眠数据 编辑:程序博客网 时间:2024/06/10 23:54

觉得minix的块高速缓存很不错,参照《minix操作系统设计与实现》代码和思想自己写了一遍,练练手。。。图片也来源于此书。。。


minix块高速缓存主要分为,空闲链表LRU和hash表。当数据块的引用计数count为零时将hash表中的数据块放入空闲链表中,但此时并不将其从hash链中删除,因为可能后续的请求还会要求此数据块,当后续调用getBlock()请求此数据块时,先在hash表中搜索,如果搜索到且当前的数据块不在LRU中则直接返回数据块,如果在LRU中则将其中LRU链中删除,如果不在hash表中则直接在LRU链中搜索,如果搜索不到则从LRU链的链头取一个分配给用户,用户再读数据到此缓存中。当用户调用putBlock释放数据块时,如果数据块的count的值为0,那么将数据块直接插入到LRU链中即可,同样也不删除其在hash链中的位置。这种操作使得当再次需要此数据块时效率变得较高。

自己实现的代码如下:
头文件hashBuf.h
#ifndef __HASHBUF_H__
#define __HASHBUF_H__

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <stdlib.h>
#ifdef    __cplusplus
extern "C"{
#endif

#define    NO_DEV        (-1)
#define TEST_DEV    (0)

#define BLOCK_SIZE    1024
#define    HASH_SIZE    128
#define    NR_BUFS        80
#define HASH_MASK    127

/*blockBuf->dirty value*/
#define    CLEAN    0    /*CLEAN means the block have not modify*/
#define    DIRTY    1

struct blockBuf{
    union {
        char    data[BLOCK_SIZE];/*data block*/
    }b;
    struct blockBuf        *next;/*used to link all free bufs*/
    struct blockBuf        *prev;/*used to link all free bufs*/
    struct blockBuf        *hash;/*used to link bufs on hash chains*/
   
    int        device;        /*device number*/
    int        blockNum;    /*block number*/
    char    dirty;        /*CLEAN or DIRTY*/
    char    count;        /*number of users of this buf*/
};
void initBuf(void);
struct blockBuf *getBlock(int device,int blockNum);
void putBlock(struct blockBuf *blockBuf);

#ifdef __cplusplus
}
#endif
#endif
/*******************************************************/

.cpp文件如下:
#include "hashBuf.h"

#ifdef    __cplusplus
extern "C"{
#endif

struct    blockBuf    blockBuf[NR_BUFS];
struct    blockBuf    *front;
struct    blockBuf    *rear;
struct    blockBuf    *hashTable[HASH_SIZE];

static    inline int    hashNum(int    blockNum);
static inline void rmBlockFromLRU(struct blockBuf *block);
static  inline struct blockBuf *popFromLRU(int device,int blockNum);
static    inline void pushToLRU(struct blockBuf *block);

/*this func simulation the read/write block func*/
#define WRITING        0
#define READING        1
int rwBlock(struct blockBuf *block,int    mode);

struct blockBuf *getBlock(int device,int blockNum)
{
    int b;
    struct    blockBuf    *bp=NULL;
    struct    blockBuf    *prev=NULL;
    struct    blockBuf    *next=NULL;

    if(device==NO_DEV)
        return    NULL;
    b=hashNum(blockNum);
    bp=hashTable[b];
   
    while(bp!=NULL){/*find block in hash chain*/
        if(bp->device==device&&bp->blockNum==blockNum){
            if(bp->count==0){
                rmBlockFromLRU(bp);
            }
            bp->count++;
            return bp;
        }
        bp=bp->hash;
    }
    /*hash chain have not this block,find it in LRU chain or get a new block from LRU chain*/
    bp=popFromLRU(device,blockNum);
    if(NULL==bp)/*no free block*/
    {
        return NULL;
    }
    if(bp->device!=device||bp->blockNum!=blockNum){
        /*delete it from it's source hash chain*/
        if(bp->dirty==DIRTY){
            rwBlock(bp,WRITING);
            //bp->dirty=CLEAN;
        }
        prev=next=hashTable[hashNum(bp->blockNum)];
        while(next!=NULL){
            if(next==bp){
                prev->hash=bp->hash;
                if(next==prev)
                    hashTable[hashNum(bp->blockNum)]=NULL;
            }
            prev=next;
            next=next->hash;
        }
        /*read new block,and set the new block to new hash chain*/
        bp->device=device;
        bp->blockNum=blockNum;
        rwBlock(bp,READING);
        bp->dirty=CLEAN;
        bp->hash=hashTable[b];
        hashTable[b]=bp;
    }
    bp->count++;
    return bp;
}

void putBlock(struct blockBuf *blockBuf)
{
    if(blockBuf->count>0)
        blockBuf->count--;
    if(blockBuf->count!=0)/*the block still in use*/
        return;   
    pushToLRU(blockBuf);
    if(blockBuf->dirty==DIRTY){
        rwBlock(blockBuf,WRITING);
        blockBuf->dirty=CLEAN;
    }
}

void initBuf(void)
{
    int    i;
   
    blockBuf[NR_BUFS-1].next=NULL;
    blockBuf[NR_BUFS-1].dirty=CLEAN;
    blockBuf[NR_BUFS-1].count=0;
    blockBuf[NR_BUFS-1].blockNum=-1;
    blockBuf[NR_BUFS-1].device=NO_DEV;
    blockBuf[0].prev=NULL;
    for(i=0;i<NR_BUFS-1;i++){
        blockBuf[i].device=TEST_DEV;
        blockBuf[i].blockNum=-1;
        blockBuf[i].dirty=CLEAN;
        blockBuf[i].count=0;
        blockBuf[i].hash=NULL;
        blockBuf[i].next=&blockBuf[i+1];
        blockBuf[i+1].prev=&blockBuf[i];   
    }
   
    for(i=0;i<HASH_SIZE;i++){
        hashTable[i]=NULL;
    }

    front=&blockBuf[0];
    rear=&blockBuf[NR_BUFS-1];
}


/*将hash链的元素放回LRU链中*/
static    inline void pushToLRU(struct blockBuf *block)
{
    if(rear!=NULL){
        rear->next=block;
    }
    block->next=NULL;
    block->prev=rear;
    rear=block;
    if(front==NULL)
        front=block;
}

/*从LRU链中取一个元素*/
static inline struct blockBuf *popFromLRU(int device,int blockNum)
{
    struct blockBuf        *bp=NULL;
    if(NULL==front){
        return NULL;
    }
    /*first search from the LRU for the device's block,
     *if have not this device's block,then get the front block buf to user
     */
    /*bp=front;
    while(bp!=NULL){
        if(bp->device==device){
            if(bp->blockNum==blockNum){
                rmBlockFromLRU(bp);
                return bp;
            }
        }
        bp=bp->next;
    }*/
    /*have not this device's block,return the front block*/
    bp=front;
    rmBlockFromLRU(bp);
    return bp;
}

static inline void rmBlockFromLRU(struct blockBuf *block)
{
    struct blockBuf    *prev=NULL;
    struct blockBuf *next=NULL;

    if(NULL==block)
        return;

    prev=block->prev;
    next=block->next;
   
    if(NULL!=prev){
        prev->next=next;
    }else{
        front=next;
    }

    if(NULL!=next){
        next->prev=prev;
    }else{
        rear=prev;
    }
    block->next=NULL;
    block->prev=NULL;
}
/*求取hash值*/
static    inline int    hashNum(int    blockNum)
{
    return (blockNum&HASH_MASK);
}

/*********************test func**************************************/
/*this func simulation the rwblock func*/
int rwBlock(struct blockBuf *block,int    mode)
{
    switch(mode){
    case READING:
        printf("test reading %d\n",block->blockNum);
        return 1;
        break;
    case WRITING:
        printf("test writing %d\n",block->blockNum);
        return 1;
        break;
    default:
        printf("have not this mode\n");
        return 0;   
    }
}
#ifdef __cplusplus
}
#endif
/*******************************************************/