溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么使用C++實(shí)現(xiàn)頁(yè)面的緩沖區(qū)管理器

發(fā)布時(shí)間:2022-08-02 09:21:56 來(lái)源:億速云 閱讀:136 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“怎么使用C++實(shí)現(xiàn)頁(yè)面的緩沖區(qū)管理器”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“怎么使用C++實(shí)現(xiàn)頁(yè)面的緩沖區(qū)管理器”文章能幫助大家解決問(wèn)題。

1. 實(shí)驗(yàn)?zāi)繕?biāo)

本次實(shí)驗(yàn)要實(shí)現(xiàn)一個(gè)頁(yè)面的緩沖區(qū)管理器。

具體要實(shí)現(xiàn)以下的函數(shù):

~BufMgr():

清除所有臟頁(yè)并釋放緩沖池和 BufDesc 表

void advanceClock():

用來(lái)找到下一個(gè)時(shí)鐘的位置

void allocBuf(FrameId& frame):

使用時(shí)鐘算法分配自由幀;如有必要,將臟頁(yè)寫回磁盤。

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

通過(guò)調(diào)用 lookup()方法檢查頁(yè)是否已經(jīng)在緩沖池中。當(dāng)頁(yè)不在緩沖池中可以在哈希表上拋出 HashNotFoundException 以獲取幀編號(hào)。

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

減少一個(gè)頁(yè)面的占用次數(shù)

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

通過(guò)調(diào)用 file->allocatePage()方法在指定的文件中分配一個(gè)空頁(yè)。此方法將返回新分配的頁(yè)。然后調(diào)用 allocBuf()以獲取緩沖池幀。接下來(lái),將一個(gè)條目插入到哈希表中,并在幀上調(diào)用 Set(),以正確設(shè)置它。

void disposePage(File* file, const PageId pageNo)

功能是釋放一個(gè)頁(yè)面

void flushFile(File* file)

功能是找到含有對(duì)應(yīng)文件的頁(yè)面,并釋放

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í)鐘提前到緩沖池的下一幀。

如果指針超過(guò)了最大值,進(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ū)尋找可用的頁(yè)面。如果是沒(méi)有被使用過(guò)的頁(yè)面,直接進(jìn)行分配。如果緩沖區(qū)所有的頁(yè)面都被占用,那么會(huì)進(jìn)行報(bào)錯(cuò) BufferExceededException()。如果找到臟頁(yè),會(huì)將它寫回磁盤,并將臟頁(yè)標(biāo)記給清除。如果不是臟頁(yè),那么就進(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);
    }
}

如果頁(yè)面在緩沖池中,增加它的占用次數(shù),調(diào)用 page 返回指向該頁(yè)面的指針。

如果頁(yè)面不在緩沖池中,那么將頁(yè)面讀取到緩沖池,插入哈希表中,調(diào)用 set 正確設(shè)置該界面,調(diào)用 page 返回指向該頁(yè)面的指針。

void BufMgr::unPinPage(File *file, const PageId pageNo, const bool dirty) {
    FrameId frame;
    try {
        hashTable->lookup(file, pageNo, frame);
    } catch (HashNotFoundException &) {
        //沒(méi)有該頁(yè)面
        cerr << "Warning: unpinning a nonexistent page" << endl;
        return;
    }
    //找到頁(yè)面
    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);
    }
}

如果緩沖池中沒(méi)有該頁(yè)面,進(jìn)行異常提示。

如果在緩沖池中,那么將它的占用次數(shù)減少。如果占用次數(shù)為 0,進(jìn)行報(bào)錯(cuò)。

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è)表,找到含有對(duì)應(yīng)頁(yè)面的緩沖頁(yè),移除并清空該頁(yè)面。如果頁(yè)面是臟頁(yè),則將其寫回磁盤,初始化臟頁(yè)標(biāo)記。如果頁(yè)面被占用或者頁(yè)面不可用,則進(jìn)行報(bào)錯(cuò)。

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è)新頁(yè)面,加入哈希表,調(diào)用 set(),返回該頁(yè)面指針。

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è)頁(yè)面。如果它在緩沖池中,要將緩沖內(nèi)容一并刪除。

3.實(shí)驗(yàn)結(jié)果

12個(gè)樣例均能通過(guò),實(shí)驗(yàn)結(jié)果如下:

怎么使用C++實(shí)現(xiàn)頁(yè)面的緩沖區(qū)管理器

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

刪除一個(gè)頁(yè)面。如果它在緩沖池中,要將緩沖內(nèi)容一并刪除

關(guān)于“怎么使用C++實(shí)現(xiàn)頁(yè)面的緩沖區(qū)管理器”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI