This repository has been archived on 2026-04-18. You can view files and clone it, but cannot push or open issues or pull requests.
Virtual-Memory-Demo/Assets/Scripts/Simulation/PhysicalMemoryManager.cs

134 lines
3.9 KiB
C#

using System;
using System.Collections.Generic;
namespace VMdemo.Simulation
{
public readonly struct EvictionInfo
{
public EvictionInfo(bool hasEvicted, ulong evictedVpn, ulong evictedPfn)
{
HasEvicted = hasEvicted;
EvictedVpn = evictedVpn;
EvictedPfn = evictedPfn;
}
public bool HasEvicted { get; }
public ulong EvictedVpn { get; }
public ulong EvictedPfn { get; }
public static EvictionInfo None => new EvictionInfo(false, 0UL, 0UL);
}
public readonly struct AllocationResult
{
public AllocationResult(ulong assignedPfn, bool wasAlreadyResident, EvictionInfo eviction)
{
AssignedPfn = assignedPfn;
WasAlreadyResident = wasAlreadyResident;
Eviction = eviction;
}
public ulong AssignedPfn { get; }
public bool WasAlreadyResident { get; }
public EvictionInfo Eviction { get; }
}
public class PhysicalMemoryManager
{
private readonly Queue<ResidentPage> _fifoQueue = new Queue<ResidentPage>();
private readonly Dictionary<ulong, ulong> _residentByVpn = new Dictionary<ulong, ulong>();
private ulong _nextFreeFrame;
public PhysicalMemoryManager(ulong frameCount)
{
if (frameCount < 1UL)
{
throw new ArgumentOutOfRangeException(nameof(frameCount), "frameCount 必须 >= 1。");
}
FrameCount = frameCount;
_nextFreeFrame = 0UL;
}
public ulong FrameCount { get; }
public int ResidentCount => _residentByVpn.Count;
public bool TryGetResidentPfn(ulong vpn, out ulong pfn)
{
return _residentByVpn.TryGetValue(vpn, out pfn);
}
public AllocationResult AllocateForVpn(ulong vpn)
{
if (_residentByVpn.TryGetValue(vpn, out var existingPfn))
{
return new AllocationResult(existingPfn, true, EvictionInfo.None);
}
EvictionInfo evictionInfo;
ulong assignedPfn;
if (_nextFreeFrame < FrameCount)
{
assignedPfn = _nextFreeFrame;
_nextFreeFrame++;
evictionInfo = EvictionInfo.None;
}
else
{
if (_fifoQueue.Count == 0)
{
throw new InvalidOperationException("内存已满但 FIFO 队列为空,状态异常。");
}
var victim = _fifoQueue.Dequeue();
if (!_residentByVpn.Remove(victim.Vpn))
{
throw new InvalidOperationException("FIFO 淘汰项未出现在驻留映射中,状态异常。");
}
assignedPfn = victim.Pfn;
evictionInfo = new EvictionInfo(true, victim.Vpn, victim.Pfn);
}
_residentByVpn[vpn] = assignedPfn;
_fifoQueue.Enqueue(new ResidentPage(vpn, assignedPfn));
return new AllocationResult(assignedPfn, false, evictionInfo);
}
public IReadOnlyList<ulong> GetFifoVpnOrder()
{
var order = new List<ulong>(_fifoQueue.Count);
foreach (var page in _fifoQueue)
{
order.Add(page.Vpn);
}
return order;
}
public string FormatFifoQueue()
{
var order = GetFifoVpnOrder();
if (order.Count == 0)
{
return "FIFO=[]";
}
return $"FIFO=[{string.Join(",", order)}]";
}
private readonly struct ResidentPage
{
public ResidentPage(ulong vpn, ulong pfn)
{
Vpn = vpn;
Pfn = pfn;
}
public ulong Vpn { get; }
public ulong Pfn { get; }
}
}
}