C++實(shí)現(xiàn)頁面的緩沖區(qū)管理器
1. 實(shí)驗(yàn)?zāi)繕?biāo)
本次實(shí)驗(yàn)要實(shí)現(xiàn)一個(gè)頁面的緩沖區(qū)管理器。
具體要實(shí)現(xiàn)以下的函數(shù):
~BufMgr():
清除所有臟頁并釋放緩沖池和 BufDesc 表
void advanceClock():
用來找到下一個(gè)時(shí)鐘的位置
void allocBuf(FrameId& frame):
使用時(shí)鐘算法分配自由幀;如有必要,將臟頁寫回磁盤。
void readPage(File* file, const PageId PageNo, Page*& page)
通過調(diào)用 lookup()方法檢查頁是否已經(jīng)在緩沖池中。當(dāng)頁不在緩沖池中可以在哈希表上拋出 HashNotFoundException 以獲取幀編號。
void unPinPage(File* file, const PageId PageNo, const bool dirty)
減少一個(gè)頁面的占用次數(shù)
void allocPage(File* file, PageId& PageNo, Page*& page)
通過調(diào)用 file->allocatePage()方法在指定的文件中分配一個(gè)空頁。此方法將返回新分配的頁。然后調(diào)用 allocBuf()以獲取緩沖池幀。接下來,將一個(gè)條目插入到哈希表中,并在幀上調(diào)用 Set(),以正確設(shè)置它。
void disposePage(File* file, const PageId pageNo)
功能是釋放一個(gè)頁面
void flushFile(File* file)
功能是找到含有對應(yīng)文件的頁面,并釋放
2. 代碼實(shí)現(xiàn)
BufMgr::~BufMgr() { delete hashTable; delete[] bufPool; delete[] bufDescTable; }
直接調(diào)用 delete 刪除哈希表、緩沖池、緩沖池表
void BufMgr::advanceClock() { clockHand++; if (clockHand >= numBufs) { clockHand %= numBufs; } }
將時(shí)鐘提前到緩沖池的下一幀。
如果指針超過了最大值,進(jìn)行取模操作。
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; } }
遍歷棧區(qū)尋找可用的頁面。如果是沒有被使用過的頁面,直接進(jìn)行分配。如果緩沖區(qū)所有的頁面都被占用,那么會進(jìn)行報(bào)錯 BufferExceededException()。如果找到臟頁,會將它寫回磁盤,并將臟頁標(biāo)記給清除。如果不是臟頁,那么就進(jìn)行分配操作。如果它在哈希表中要將它移除。
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); } }
如果頁面在緩沖池中,增加它的占用次數(shù),調(diào)用 page 返回指向該頁面的指針。
如果頁面不在緩沖池中,那么將頁面讀取到緩沖池,插入哈希表中,調(diào)用 set 正確設(shè)置該界面,調(diào)用 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); } }
如果緩沖池中沒有該頁面,進(jìn)行異常提示。
如果在緩沖池中,那么將它的占用次數(shù)減少。如果占用次數(shù)為 0,進(jìn)行報(bào)錯。
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(); } } }
遍歷整個(gè)表,找到含有對應(yīng)頁面的緩沖頁,移除并清空該頁面。如果頁面是臟頁,則將其寫回磁盤,初始化臟頁標(biāo)記。如果頁面被占用或者頁面不可用,則進(jìn)行報(bào)錯。
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()分配一個(gè)新頁面,加入哈希表,調(diào)用 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); }
刪除一個(gè)頁面。如果它在緩沖池中,要將緩沖內(nèi)容一并刪除。
3.實(shí)驗(yàn)結(jié)果
12個(gè)樣例均能通過,實(shí)驗(yàn)結(jié)果如下:
me].Clear(); } catch (HashNotFoundException &) { } file->deletePage(PageNo); }
刪除一個(gè)頁面。如果它在緩沖池中,要將緩沖內(nèi)容一并刪除
到此這篇關(guān)于C++實(shí)現(xiàn)頁面的緩沖區(qū)管理器的文章就介紹到這了,更多相關(guān)C++緩沖區(qū)管理器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)雷霆戰(zhàn)機(jī)可視化小游戲
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)雷霆戰(zhàn)機(jī)可視化小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11C語言的可變參數(shù)函數(shù)實(shí)現(xiàn)詳解
某些情況下我們希望函數(shù)的參數(shù)個(gè)數(shù)可以根據(jù)需要確定,因此c語言引入可變參數(shù)函數(shù)。典型的可變參數(shù)函數(shù)的例子有printf()、scanf()等,下面我就開始講解2021-08-08matlab實(shí)現(xiàn)繪制玫瑰花球的示例代碼
這篇文章主要介紹了如何利用matlab實(shí)現(xiàn)繪制玫瑰花球,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Matlab有一定的幫助,需要的可以參考一下2023-08-08ubuntu系統(tǒng)下C++調(diào)用matlab程序的方法詳解
學(xué)習(xí)c++與matlab混合編程一般是通過c++調(diào)用matlab函數(shù),因?yàn)閙atlab具有強(qiáng)大的數(shù)學(xué)函數(shù)庫,然而vc++具有界面設(shè)計(jì)靈活的優(yōu)點(diǎn),下面這篇文章主要給大家介紹了關(guān)于在ubuntu系統(tǒng)下C++調(diào)用matlab程序的方法,需要的朋友可以參考下。2017-08-08簡單聊聊C++中回調(diào)函數(shù)的實(shí)現(xiàn)
回調(diào)函數(shù)就是一個(gè)通過函數(shù)指針調(diào)用的函數(shù),如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用來調(diào)用其所指向的函數(shù)時(shí),我們就說這是回調(diào)函數(shù),下面這篇文章主要給大家介紹了關(guān)于C++中回調(diào)函數(shù)實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2022-01-01