📄 memorymanager.cs
字号:
/// <summary>
/// One of two parallel arrays, one of shared owners of this page, one of shared process indexes of this page
/// </summary>
public ArrayList pidSharedOwnerList = new ArrayList();
/// <summary>
/// One of two parallel arrayz, one of shared owners of this page, one of shared process indexes of this page
/// </summary>
public ArrayList pidSharedProcessIndex = new ArrayList();
/// <summary>
/// The number this page is in addressable Memory. Set once and immutable
/// </summary>
public readonly uint pageNumber = 0;
/// <summary>
/// The address in addressable space this page is responsbile for
/// </summary>
public readonly uint addrVirtual = 0;
/// <summary>
/// The address in Process space this page is responsible for
/// </summary>
public uint addrProcessIndex = 0;
/// <summary>
/// The process address that originally allocated this page. Kept so we can free that page(s) later.
/// </summary>
public uint heapAllocationAddr = 0;
/// <summary>
/// The process that is currently using this apge
/// </summary>
public uint pidOwner = 0;
/// <summary>
/// This is only valid when
/// pidOwner != 0 and isValid == true
/// meaning the page is actually mapped and present
/// </summary>
public uint addrPhysical = 0;
/// <summary>
/// Is the page in memory now?
/// </summary>
public bool isValid;
/// <summary>
/// Has the page been changes since it was last swapped in from Disk?
/// </summary>
public bool isDirty = false;
/// <summary>
/// For statistics: How many times has this page been involved in a pageFault?
/// </summary>
public uint pageFaults = 0;
/// <summary>
/// For aging and swapping: How many times has this page's address range been accessed?
/// </summary>
public uint accessCount = 0;
/// <summary>
/// For aging and swapping: When was this page last accessed?
/// </summary>
public DateTime lastAccessed = DateTime.Now;
/// <summary>
/// Only public constructor for a Memory Page and is only called once
/// in the <see cref="MemoryManager"/> constructor
/// </summary>
/// <param name="initAddrVirtual">The address in addressable memory this page is responsible for</param>
/// <param name="isValidFlag">Is this page in memory right now?</param>
public MemoryPage(uint initAddrVirtual, bool isValidFlag)
{
isValid = isValidFlag;
if (isValid)
addrPhysical = initAddrVirtual;
addrVirtual = initAddrVirtual;
pageNumber = (addrVirtual)/CPU.pageSize;
}
}
/// <summary>
/// Represents the actual values in memory that a MemoryPage points to.
/// MemoryPageValue is serialized to disk, currently as XML, in <see cref="SwapOut"/>.
/// </summary>
[Serializable] public class MemoryPageValue
{
/// <summary>
/// The array of bytes holding the value of memory for this page
/// </summary>
[XmlArray(ElementName = "byte", Namespace = "http://www.hanselman.com")]
public byte[] memory = new byte[CPU.pageSize];
/// <summary>
/// For aging and swapping: How many times has this page's address range been accessed?
/// </summary>
public uint accessCount = 0;
/// <summary>
/// For aging and swapping: When was this page last accessed?
/// </summary>
public DateTime lastAccessed = DateTime.Now;
}
/// <summary>
/// Swaps the specified <see cref="MemoryPage"/> to disk. Currently implemented as XML for fun.
/// </summary>
/// <param name="victim">The <see cref="MemoryPage"/> to be swapped</param>
public void SwapOut(MemoryPage victim)
{
if (victim.isDirty)
{
// Generate a filename based on address and page number
string filename = System.Environment.CurrentDirectory + "/page" + victim.pageNumber + "-" + victim.addrVirtual + ".xml";
// IFormatter ser = new BinaryFormatter();
// Stream writer = new FileStream(filename, FileMode.Create);
XmlSerializer ser = new XmlSerializer(typeof(MemoryPageValue));
Stream fs = new FileStream(filename, FileMode.Create);
XmlWriter writer = new XmlTextWriter(fs, new UTF8Encoding());
MemoryPageValue pageValue = new MemoryPageValue();
// Copy the bytes from Physical Memory so we don't pageFault in a Fault Hander
byte[] bytes = new byte[CPU.pageSize];
for (int i = 0; i < CPU.pageSize; i++)
bytes[i] = CPU.physicalMemory[victim.addrPhysical+i];
// Copy details from the MemoryPage to the MemoryPageValue
pageValue.memory = bytes;
pageValue.accessCount = victim.accessCount;
pageValue.lastAccessed = victim.lastAccessed;
//Console.WriteLine("Swapping out page {0} at physical memory {1}",victim.pageNumber, victim.addrPhysical);
// Write the MemoryPageValue to disk!
ser.Serialize(writer,pageValue);
//writer.Flush();
//writer.Close();
fs.Close();
}
victim.isValid = false;
}
/// <summary>
/// Swaps in the specified <see cref="MemoryPage"/> from disk. Currently implemented as XML for fun.
/// </summary>
/// <param name="winner">The <see cref="MemoryPage"/> that is being swapped in</param>
public void SwapIn(MemoryPage winner)
{
// Generate a filename based on address and page number
string filename = System.Environment.CurrentDirectory + "/page" + winner.pageNumber + "-" + winner.addrVirtual + ".xml";
if (File.Exists(filename) && winner.isValid == false)
{
//BinaryFormatter ser = new BinaryFormatter();
//Stream reader = new FileStream(filename, FileMode.Open);
XmlSerializer ser = new XmlSerializer(typeof(MemoryPageValue));
Stream fs = new FileStream(filename, FileMode.Open);
XmlReader reader = new XmlTextReader(fs);
// Load the MemoryPageValue in from Disk!
MemoryPageValue pageValue = (MemoryPageValue)ser.Deserialize(reader);
// Copy the bytes from Physical Memory so we don't pageFault in a Fault Hander
for (int i = 0; i < CPU.pageSize; i++)
CPU.physicalMemory[winner.addrPhysical+i] = pageValue.memory[i];
//Console.WriteLine("Swapping in page {0} at physical memory {1}",winner.pageNumber, winner.addrPhysical);
winner.accessCount = pageValue.accessCount;
winner.lastAccessed = pageValue.lastAccessed;
pageValue = null;
reader.Close();
fs.Close();
File.Delete(filename);
}
else //no swap file, do nothing
{
//Console.WriteLine(filename + " doesn't exist");
}
// We are now in memory and we were involved in Page Fault
winner.isValid = true;
winner.pageFaults++;
}
/// <summary>
/// For statistical purposes only.
/// Total up how many times this Process has been involved in a Page Fault
/// </summary>
/// <param name="p">The Process to total</param>
/// <returns>number of Page Faults</returns>
public uint PageFaultsForProcess(Process p)
{
uint totalPageFaults = 0;
foreach (MemoryPage page in _pageTable)
{
if (page.pidOwner == p.PCB.pid)
{
totalPageFaults += page.pageFaults;
}
}
return totalPageFaults;
}
}
/// <summary>
/// Memory Protection: MemoryExceptions are constructed and thrown
/// when a <see cref="Process"/> accessed memory that doesn't belong to it.
/// </summary>
public class MemoryException : Exception
{
/// <summary>
/// Process ID
/// </summary>
public uint pid = 0;
/// <summary>
/// Process address in question
/// </summary>
public uint processAddress = 0;
/// <summary>
/// Public Constructor for a Memory Exception
/// </summary>
/// <param name="pidIn">Process ID</param>
/// <param name="addrIn">Process address</param>
public MemoryException(uint pidIn, uint addrIn)
{
pid = pidIn;
processAddress = addrIn;
}
/// <summary>
/// Pretty printing for MemoryExceptions
/// </summary>
/// <returns>Formatted string about the MemoryException</returns>
public override string ToString()
{
return String.Format("Process {0} tried to access memory at address {1} and will be terminated! ",pid, processAddress);
}
}
/// <summary>
/// Memory Protection: MemoryExceptions are constructed and thrown
/// when a <see cref="Process"/> accessed memory that doesn't belong to it.
/// </summary>
public class StackException : Exception
{
/// <summary>
/// Process ID
/// </summary>
public uint pid = 0;
/// <summary>
/// Num of Bytes more than the stack could handle
/// </summary>
public uint tooManyBytes = 0;
/// <summary>
/// Public Constructor for a Memory Exception
/// </summary>
/// <param name="pidIn">Process ID</param>
/// <param name="tooManyBytesIn">Process address</param>
public StackException(uint pidIn, uint tooManyBytesIn)
{
pid = pidIn;
tooManyBytes = tooManyBytesIn;
}
/// <summary>
/// Pretty printing for MemoryExceptions
/// </summary>
/// <returns>Formatted string about the MemoryException</returns>
public override string ToString()
{
return String.Format("Process {0} tried to push {1} too many bytes on to the stack and will be terminated! ",pid, tooManyBytes);
}
}
/// <summary>
/// Memory Protection: MemoryExceptions are constructed and thrown
/// when a <see cref="Process"/> accessed memory that doesn't belong to it.
/// </summary>
public class HeapException : Exception
{
/// <summary>
/// Process ID
/// </summary>
public uint pid = 0;
/// <summary>
/// Num of Bytes more than the stack could handle
/// </summary>
public uint tooManyBytes = 0;
/// <summary>
/// Public Constructor for a Memory Exception
/// </summary>
/// <param name="pidIn">Process ID</param>
/// <param name="tooManyBytesIn">Process address</param>
public HeapException(uint pidIn, uint tooManyBytesIn)
{
pid = pidIn;
tooManyBytes = tooManyBytesIn;
}
/// <summary>
/// Pretty printing for MemoryExceptions
/// </summary>
/// <returns>Formatted string about the MemoryException</returns>
public override string ToString()
{
return String.Format("Process {0} tried to alloc {1} bytes more from the heap than were free and will be terminated! ",pid, tooManyBytes);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -