網站首頁 編程語言 正文
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);
}
刪除一個頁面。如果它在緩沖池中,要將緩沖內容一并刪除
原文鏈接:https://biyezuopin.blog.csdn.net/article/details/126084368
相關推薦
- 2021-12-10 k8s部署ingress-nginx的方法步驟_nginx
- 2022-10-21 Go?Ticker?周期性定時器用法及實現原理詳解_Golang
- 2022-10-17 VSCode安裝Django插件后實現html語法提示的方法步驟_python
- 2022-02-02 uni 修改數據頁面不重新渲染
- 2022-05-22 python?使用tkinter與messagebox寫界面和彈窗_python
- 2022-10-30 解決docker訪問外部https數字證書問題_docker
- 2022-04-21 C#實現chart控件動態曲線繪制_C#教程
- 2022-04-05 availableProcessors is already set to [8], rejecti
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支