C++实现页面的缓冲区管理器

 更新时间:2022年08月01日 16:16:58   作者:biyezuopinvip  
这篇文章主要介绍了C++实现页面的缓冲区管理器,文章围绕主题展开详细的内容介绍具有一定的参考价值,需要的小伙伴可以参考一下

1. 实验目标

本次实验要实现一个页面的缓冲区管理器。

具体要实现以下的函数:

~BufMgr():

清除所有脏页并释放缓冲池和 BufDesc 表

void advanceClock():

用来找到下一个时钟的位置

void allocBuf(FrameId& frame):

使用时钟算法分配自由帧;如有必要,将脏页写回磁盘。

void readPage(File* file, const PageId PageNo, Page*& page)

通过调用 lookup()方法检查页是否已经在缓冲池中。当页不在缓冲池中可以在哈希表上抛出 HashNotFoundException 以获取帧编号。

void unPinPage(File* file, const PageId PageNo, const bool dirty)

减少一个页面的占用次数

void allocPage(File* file, PageId& PageNo, Page*& page)

通过调用 file->allocatePage()方法在指定的文件中分配一个空页。此方法将返回新分配的页。然后调用 allocBuf()以获取缓冲池帧。接下来,将一个条目插入到哈希表中,并在帧上调用 Set(),以正确设置它。

void disposePage(File* file, const PageId pageNo)

功能是释放一个页面

void flushFile(File* file)

功能是找到含有对应文件的页面,并释放

2. 代码实现

BufMgr::~BufMgr() {
    delete hashTable;
    delete[] bufPool;
    delete[] bufDescTable;
}

直接调用 delete 删除哈希表、缓冲池、缓冲池表

void BufMgr::advanceClock() {
    clockHand++;
    if (clockHand >= numBufs) {
        clockHand %= numBufs;
    }
}

将时钟提前到缓冲池的下一帧。

如果指针超过了最大值,进行取模操作。

void BufMgr::allocBuf(FrameId &frame) {
    unsigned pinned = 0;
    while (true) {
        advanceClock();
        if (!bufDescTable[clockHand].valid) {
            frame = clockHand;
            return;
        }
        if (bufDescTable[clockHand].refbit) {
            bufDescTable[clockHand].refbit = false;
            continue;
        }
        if (bufDescTable[clockHand].pinCnt) {
            pinned++;
            if (pinned == numBufs) {
                throw BufferExceededException();
            } else {
                continue;
            }
        }
        if (bufDescTable[clockHand].dirty) {
            bufDescTable[clockHand].file->writePage(bufPool[clockHand]);
            bufDescTable[clockHand].dirty = false;
        }
        frame = clockHand;
        if (bufDescTable[clockHand].valid) {
            try {
                hashTable->remove(bufDescTable[clockHand].file, bufDescTable[clockHand].pageNo);
            }
            catch (HashNotFoundException &) {
            }
        }
        break;
    }
}

遍历栈区寻找可用的页面。如果是没有被使用过的页面,直接进行分配。如果缓冲区所有的页面都被占用,那么会进行报错 BufferExceededException()。如果找到脏页,会将它写回磁盘,并将脏页标记给清除。如果不是脏页,那么就进行分配操作。如果它在哈希表中要将它移除。

void BufMgr::readPage(File *file, const PageId pageNo, Page *&page) {
    FrameId frame;
    try {
        hashTable->lookup(file, pageNo, frame);
        bufDescTable[frame].refbit = true;
        bufDescTable[frame].pinCnt++;
        page = (bufPool + frame);
    } catch (HashNotFoundException &) {
        allocBuf(frame);
        bufPool[frame] = file->readPage(pageNo);
        hashTable->insert(file, pageNo, frame);
        bufDescTable[frame].Set(file, pageNo);
        page = (bufPool + frame);
    }
}

如果页面在缓冲池中,增加它的占用次数,调用 page 返回指向该页面的指针。

如果页面不在缓冲池中,那么将页面读取到缓冲池,插入哈希表中,调用 set 正确设置该界面,调用 page 返回指向该页面的指针。

void BufMgr::unPinPage(File *file, const PageId pageNo, const bool dirty) {
    FrameId frame;
    try {
        hashTable->lookup(file, pageNo, frame);
    } catch (HashNotFoundException &) {
        //没有该页面
        cerr << "Warning: unpinning a nonexistent page" << endl;
        return;
    }
    //找到页面
    if (bufDescTable[frame].pinCnt > 0) {
        bufDescTable[frame].pinCnt--;
        if (dirty) {
            bufDescTable[frame].dirty = true;
        }
    } else {
        //pin = 0,抛出异常
        throw PageNotPinnedException(bufDescTable[frame].file->filename(), bufDescTable[frame].pageNo, frame);
    }
}

如果缓冲池中没有该页面,进行异常提示。

如果在缓冲池中,那么将它的占用次数减少。如果占用次数为 0,进行报错。

void BufMgr::flushFile(const File *file) {
    for (FrameId fi = 0; fi < numBufs; fi++) {
        if (bufDescTable[fi].file == file) {
            if (!bufDescTable[fi].valid) {
                throw BadBufferException(fi, bufDescTable[fi].dirty, bufDescTable[fi].valid, bufDescTable[fi].refbit);
            }
            if (bufDescTable[fi].pinCnt > 0) {
                throw PagePinnedException(file->filename(), bufDescTable[fi].pageNo, fi);
            }
            if (bufDescTable[fi].dirty) {
                bufDescTable[fi].file->writePage(bufPool[fi]);
                bufDescTable[fi].dirty = false;
            }
            hashTable->remove(file, bufDescTable[fi].pageNo);
            bufDescTable[fi].Clear();
        }
    }
}

遍历整个表,找到含有对应页面的缓冲页,移除并清空该页面。如果页面是脏页,则将其写回磁盘,初始化脏页标记。如果页面被占用或者页面不可用,则进行报错。

void BufMgr::allocPage(File *file, PageId &pageNo, Page *&page) {
    FrameId frame;
    Page p = file->allocatePage();
    allocBuf(frame);
    bufPool[frame] = p;
    pageNo = p.page_number();
    hashTable->insert(file, pageNo, frame);
    bufDescTable[frame].Set(file, pageNo);
    page = bufPool + frame;
}

掉用 allocatePage()分配一个新页面,加入哈希表,调用 set(),返回该页面指针。

void BufMgr::disposePage(File *file, const PageId PageNo) {
    FrameId frame;
    try {
        hashTable->lookup(file, PageNo, frame);
        hashTable->remove(file, PageNo);
        bufDescTable[frame].Clear();
    } catch (HashNotFoundException &) {
    }
    file->deletePage(PageNo);
}

删除一个页面。如果它在缓冲池中,要将缓冲内容一并删除。

3.实验结果

12个样例均能通过,实验结果如下:

me].Clear();
} catch (HashNotFoundException &) {
}
file->deletePage(PageNo);
}

删除一个页面。如果它在缓冲池中,要将缓冲内容一并删除

到此这篇关于C++实现页面的缓冲区管理器的文章就介绍到这了,更多相关C++缓冲区管理器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++利用栈实现中缀表达式转后缀表达式

    C++利用栈实现中缀表达式转后缀表达式

    这篇文章主要为大家详细介绍了C++利用栈实现中缀表达式转后缀表达式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • C++中的运算符和运算符优先级总结

    C++中的运算符和运算符优先级总结

    这篇文章主要介绍了C++中的运算符和运算符优先级总结,主要整理了算术、关系、逻辑、位和赋值运算符的用法,需要的朋友可以参考下
    2016-05-05
  • 大家注意vector, list, set, map成员函数erase

    大家注意vector, list, set, map成员函数erase

    set和map是由红黑树来实现的,当erase的时候迭代器就失效了,也就是说我们要在迭代器失效之前保留一个副本,根据这个副本我们才能继续遍历下一个元素
    2013-09-09
  • C语言中单链表的基本操作(创建、销毁、增删查改等)

    C语言中单链表的基本操作(创建、销毁、增删查改等)

    这篇文章主要介绍了C语言中单链表的基本操作(创建、销毁、增删查改等),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • C语言数组应用实现三子棋游戏

    C语言数组应用实现三子棋游戏

    这篇文章主要为大家详细介绍了C语言数组应用实现三子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C语言学生信息管理系统设计与实现

    C语言学生信息管理系统设计与实现

    这篇文章主要为大家详细介绍了C语言学生信息管理系统设计与实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • 带你理解C语言中的汉诺塔公式

    带你理解C语言中的汉诺塔公式

    大家好,本篇文章主要讲的是带你理解C语言中的汉诺塔公式,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • 浅析string 与char* char[]之间的转换

    浅析string 与char* char[]之间的转换

    与char*不同的是,string不一定以NULL('\0')结束。string长度可以根据length()得到,string可以根据下标访问。所以,不能将string直接赋值给char*
    2013-10-10
  • opencv图片的任意角度旋转实现示例

    opencv图片的任意角度旋转实现示例

    这篇博客将介绍如何使用OpenCV旋转图像任意角度,实现各个角度的旋转,具有一定的参考价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • C++ 左值引用与一级指针示例详解

    C++ 左值引用与一级指针示例详解

    这篇文章主要介绍了C++ 左值引用与一级指针,本文给大家介绍了C++ (左值)引用和指针简介,结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09

最新评论