页帧的寻找

一、内核对物理内存的管理(MmPfnDatabase)

Windows通过几个全局变量来对物理内存进行管理:

MmPfnDatabase,页帧数据库(也叫FPN数据库),是MMPFN结构体类型的数组,它的索引是物理地址页帧号。

1: kd> dq mmpfndatabase
fffff800`04119228  fffffa80`00000000 000001f4`00000040
fffff800`04119238  00000000`00000390 00000000`00000000
fffff800`04119248  00080000`00000001 00000001`ffffffff
fffff800`04119258  fffffa80`18de7000 01d84429`7d237fba
fffff800`04119268  fffffa80`18e41580 fffffa80`18e725c0
fffff800`04119278  00000000`00006c00 00000000`5c7f8000
fffff800`04119288  fffffa80`18d47b50 00000000`00000001
fffff800`04119298  fffffa80`18eaa870 00026161`00000000

ffffa80`00000000 则是存放物理地址0,大小一个页(0x1000)的物理地址信息

nt!_MMPFN
   +0x000 u1               : <unnamed-tag>
   +0x008 u2               : <unnamed-tag>
   +0x010 PteAddress       : Ptr64 _MMPTE
   +0x010 VolatilePteAddress : Ptr64 Void
   +0x010 Lock             : Int4B
   +0x010 PteLong          : Uint8B
   +0x018 u3               : <unnamed-tag>
   +0x01c UsedPageTableEntries : Uint2B
   +0x01e VaType           : UChar
   +0x01f ViewCount        : UChar
   +0x020 OriginalPte      : _MMPTE
   +0x020 AweReferenceCount : Int4B
   +0x028 u4               : <unnamed-tag>

假设我们要找第三个物理地址,也就是物理地址是3000;页帧数据库+_MMPFN大小*第几个

ffffa80`00000000+0x30*3

1: kd> dt _mmpfn fffffa80`00000000+30*3
nt!_MMPFN
   +0x000 u1               : <unnamed-tag>
   +0x008 u2               : <unnamed-tag>
   +0x010 PteAddress       : 0xfffff6ff`ffffe838 _MMPTE
   +0x010 VolatilePteAddress : 0xfffff6ff`ffffe838 Void
   +0x010 Lock             : 0n-6088
   +0x010 PteLong          : 0xfffff6ff`ffffe838
   +0x018 u3               : <unnamed-tag>
   +0x01c UsedPageTableEntries : 0
   +0x01e VaType           : 0 ''
   +0x01f ViewCount        : 0 ''
   +0x020 OriginalPte      : _MMPTE
   +0x020 AweReferenceCount : 0n0
   +0x028 u4               : <unnamed-tag>
1: kd> !pte 0xfffff6ff`ffffe838
                                           VA ffffffffffd07000
PXE at FFFFF6FB7DBEDFF8    PPE at FFFFF6FB7DBFFFF8    PDE at FFFFF6FB7FFFFFF0    PTE at FFFFF6FFFFFFE838
contains 000000000020F063  contains 00000000001FF063  contains 00000000001FE063  contains 0000000000003163
pfn 20f       ---DA--KWEV  pfn 1ff       ---DA--KWEV  pfn 1fe       ---DA--KWEV  pfn 3         -G-DA--KWEV

换而言之,物理地址/0x1000=页帧数据库所在位置

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是常见的三种操作系统页面置换算法的 C++ 代码实现: 1. 先进先出(FIFO)页面置换算法: ```cpp #include <iostream> #include <queue> using namespace std; int main() { queue<int> fifo; // 存放页面的队列 int page_num, frame_num, page_fault = 0; // 页面数、帧数、页面失效次数 cin >> page_num >> frame_num; int* pages = new int[page_num]; // 存放页面的数组 for (int i = 0; i < page_num; ++i) { cin >> pages[i]; } for (int i = 0; i < page_num; ++i) { int page = pages[i]; if (fifo.size() < frame_num) { // 如果队列未满,直接加入队尾 fifo.push(page); ++page_fault; } else { // 如果队列已满,弹出队头,再加入队尾 int front_page = fifo.front(); if (front_page != page) { fifo.pop(); fifo.push(page); ++page_fault; } } } cout << "FIFO: " << page_fault << endl; delete[] pages; return 0; } ``` 2. 最近最久未使用(LRU)页面置换算法: ```cpp #include <iostream> #include <list> #include <unordered_map> using namespace std; int main() { list<int> lru; // 存放页面的双向链表 unordered_map<int, list<int>::iterator> map; // 存放页面和其在链表中的迭代器 int page_num, frame_num, page_fault = 0; // 页面数、帧数、页面失效次数 cin >> page_num >> frame_num; int* pages = new int[page_num]; // 存放页面的数组 for (int i = 0; i < page_num; ++i) { cin >> pages[i]; } for (int i = 0; i < page_num; ++i) { int page = pages[i]; auto iter = map.find(page); if (iter != map.end()) { // 如果页面已在链表中,先删除再插入到链表尾部 lru.erase(iter->second); map.erase(iter); } if (lru.size() == frame_num) { // 如果链表已满,删除链表头部(最近最久未使用的页面) int front_page = lru.front(); lru.pop_front(); map.erase(front_page); } // 将新页面插入链表尾部,并在 map 中记录迭代器 lru.push_back(page); map[page] = --lru.end(); ++page_fault; } cout << "LRU: " << page_fault << endl; delete[] pages; return 0; } ``` 3. 时钟页面置换算法: ```cpp #include <iostream> #include <vector> using namespace std; int main() { vector<int> clock; // 存放页面的数组 vector<bool> ref; // 存放页面的引用位 int page_num, frame_num, page_fault = 0; // 页面数、帧数、页面失效次数 cin >> page_num >> frame_num; int* pages = new int[page_num]; // 存放页面的数组 for (int i = 0; i < page_num; ++i) { cin >> pages[i]; } for (int i = 0; i < page_num; ++i) { int page = pages[i]; bool found = false; for (int j = 0; j < clock.size(); ++j) { if (clock[j] == page) { // 如果页面已在数组中,将其引用位设置为 true ref[j] = true; found = true; break; } } if (!found) { // 如果页面不在数组中,寻找第一个引用位为 false 的页面 while (true) { if (!ref[0]) { // 如果找到了,将其替换为新页面 clock[0] = page; ref[0] = true; break; } else { // 如果没找到,将所有页面的引用位都设为 false ref[0] = false; clock.push_back(clock[0]); ref.push_back(false); clock.erase(clock.begin()); ref.erase(ref.begin()); } } ++page_fault; } } cout << "Clock: " << page_fault << endl; delete[] pages; return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值