免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1189 | 回复: 0
打印 上一主题 下一主题

Buffer Cache ——模拟实验(1) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-07-12 11:12 |只看该作者 |倒序浏览

这是参照《UNIX操作系统设计》一书中的缓冲区算法做的缓冲区模拟实验,没有delayed-write, 没有实际块读写。

为了容易观察,hashtable的大小只有2,所有bufferheader的数量只有5个。

测试的输入内容是
7
0 0 3
0 1 5
1 0 9
1 1 8
0 2 13
3 4 43
2 4 22



#include stdio.h>
#define HASHSIZE 2
#define NR_BUFFER 5
struct bufferhead {
    int data;
    int devnum;
    int blknum;
    int busy;
    struct bufferhead *prev_hash;
    struct bufferhead *next_hash;
    struct bufferhead *prev_free;
    struct bufferhead *next_free;
};
struct bufferhead *hashtable[HASHSIZE];
struct bufferhead *freelist = &(struct bufferhead){};
struct bufferhead bfs[NR_BUFFER];
#define HASH(devnum, blknum) ((devnum) ^ (blknum)) % HASHSIZE
void insert_to_hashqueue(struct bufferhead *p) {
    int i;
    i = HASH(p->devnum, p->blknum);
    if(hashtable == NULL){
        hashtable = p;
        p->next_hash = p;
        p->prev_hash = p;
    }else{
        p->next_hash = hashtable->next_hash;
        p->prev_hash = hashtable;
        hashtable->next_hash = p;
        p->next_hash->prev_hash = p;
    }
}
void remove_from_hashqueue(struct bufferhead *p) {
    int i;
    i = HASH(p->devnum, p->blknum);
    if(p->next_hash)
        p->next_hash->prev_hash = p->prev_hash;
    if(p->prev_hash)
        p->prev_hash->next_hash = p->next_hash;
    //if p is head
    if(hashtable == p){
        //and it is the only one
        if(hashtable->next_hash == p)
            hashtable = NULL;
        else
            hashtable = p->next_hash;
    }
}
struct bufferhead *getblk(int devnum, int blknum) {
    int i, found;
    struct bufferhead *p;
    found = 0;
    while(!found){
        //search the buffer for the block in hashtable
        i = HASH(devnum, blknum);
        if(hashtable != NULL) {
            p = hashtable;
            while(p != hashtable->prev_hash &&
                  !(p->devnum == devnum && p->blknum == blknum)) {
                p = p->next_hash;
            }
            if(p == hashtable->prev_hash){//if this is the last
                //and it match
                if(p->devnum == devnum && p->blknum == blknum)
                    found = 1;
            }
            else
                found = 1;
        }
        //we find it
        if(found) {
            //but it is busy, so sleep until it is release, then search again
            if(p->busy) {
                pause();
                found = 0;
                continue;
            }
            //it is free
            p->busy = 1;
            p->prev_free->next_free = p->next_free;
            p->next_free->prev_free = p->prev_free;
            return p;
        }else {// we cannot find it
            //the free list is empty, so, sleep until a buffer is released
            if(freelist->next_free == freelist) {
                pause();
                continue;
            }
            //do not consider delay write, so just remove it from freelist and
            //old hash queue, and add to new hashqueue
            //allocate a new buffer from the free list
            p = freelist->next_free;
            freelist->next_free = p->next_free;
            p->next_free->prev_free = freelist;
            remove_from_hashqueue(p);
            p->devnum = devnum;
            p->blknum = blknum;
            p->busy = 1;
            insert_to_hashqueue(p);
            return p;
        }
    }
}
void brelse(struct bufferhead *p) {
    p->busy = 0;
    p->next_free = freelist;
    p->prev_free = freelist->prev_free;
    freelist->prev_free = p;
    p->prev_free->next_free = p;
}
void init_bufferhead() {
    int i;
   
    freelist->next_free = bfs;
    freelist->prev_free = bfs + NR_BUFFER - 1;
    for(i = 0; i  NR_BUFFER; i++) {
        bfs.busy = 0;
        bfs.next_free = bfs + i + 1;
        bfs.prev_free = bfs + i - 1;
    }
    bfs[0].prev_free = freelist;
    bfs[NR_BUFFER - 1].next_free = freelist;
}
void testshow() {
    int i;
    struct bufferhead *p;
    for(i = 0; i  HASHSIZE; i++){
        p = hashtable;
        while(p && p->next_hash != hashtable){
            printf("(%d, %d, %d) ", p->devnum, p->blknum, p->data);
            p = p->next_hash;
        }
        if(p) {
            printf("(%d, %d, %d)\n", p->devnum, p->blknum, p->data);
        }
    }
    printf("---------------------------------\n");
}
int main() {
    struct bufferhead *p;
    int n, m, devnum, blknum, data;
   
    init_bufferhead();
    scanf("%d", &n);
    while(n > 0) {
        scanf("%d%d%d", &devnum, &blknum, &data);
        p = getblk(devnum, blknum);
        p->data = data;
        brelse(p);
        testshow();
        n--;
    }
    //test too
    p = getblk(1, 1);
    printf("%d\n", p->data);
    brelse(p);
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/77943/showart_1993763.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP