⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memorymanager.cs

📁 CSharp写的一个超微软操作系统
💻 CS
📖 第 1 页 / 共 3 页
字号:
// ------------------------------------------------------------------------------
// <copyright from='2002' to='2002' company='Scott Hanselman'>
//    Copyright (c) Scott Hanselman. All Rights Reserved.   
// </copyright> 
// ------------------------------------------------------------------------------
//
// Scott Hanselman's Tiny Academic Virtual CPU and OS
// Copyright (c) 2002, Scott Hanselman (scott@hanselman.com)
// All rights reserved.
// 
// A BSD License
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 
// Redistributions of source code must retain the above copyright notice, 
// this list of conditions and the following disclaimer. 
// Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation 
// and/or other materials provided with the distribution. 
// Neither the name of Scott Hanselman nor the names of its contributors
// may be used to endorse or promote products derived from this software without
// specific prior written permission. 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
// THE POSSIBILITY OF SUCH DAMAGE.
//
using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Threading;
using System.Text;
using System.Configuration;
using System.Runtime.Serialization.Formatters.Binary;

namespace Hanselman.CST352
{
	/// <summary>
	/// The MemoryManager for the <see cref="OS"/>.   All memory accesses by a <see cref="Process"/> 
	/// go through this class.
	/// </summary>
	/// <example>
	/// theOS.memoryMgr[processId, 5]; //accesses memory at address 5
	/// </example>
	public class MemoryManager
	{
		private ArrayList _pageTable;
		
		//BitArray freePhysicalPages = new BitArray((int)(CPU.physicalMemory.Length/CPU.pageSize), true);
		private  bool[] freePhysicalPages = new bool[(int)(CPU.physicalMemory.Length/CPU.pageSize)];

		/// <summary>
		/// Total ammount of addressable memory.  This is set in the Constructor. 
		/// Once set, it is readonly
		/// </summary>
		public readonly uint virtualMemSize = 0;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="virtualMemSizeIn"></param>
		public MemoryManager(uint virtualMemSizeIn)
		{
			//
			// Find a size for addressableMemory that is on a page boundary
			//
			virtualMemSize = CPU.UtilRoundToBoundary(virtualMemSizeIn, CPU.pageSize);

			//
			// Size of memory must be a factor of CPU.pageSize
			// This was asserted when the CPU initialized memory
			//
			uint physicalpages = (uint)(CPU.physicalMemory.Length/CPU.pageSize);
			uint addressablepages = (uint)(virtualMemSize/CPU.pageSize);
			
			_pageTable = new ArrayList((int)addressablepages);

			// Delete all our Swap Files
			foreach (string f in Directory.GetFiles(".","*.xml"))
				File.Delete(f);

			// For all off addressable memory...
			// Make the pages in physical and the pages that aren't in physical
			for (uint i = 0;i < virtualMemSize; i+=CPU.pageSize)
			{
				// Mark the Pages that are in physical memory as "false" or "not free"
				MemoryPage p;
				if (i < CPU.physicalMemory.Length) 
				{
					p = new MemoryPage(i, true);
					freePhysicalPages[(int)(i/CPU.pageSize)] = false;
				}
				else p = new MemoryPage(i, false);

				_pageTable.Add(p);
			}

			//
			// Cordon off some shared memory regions...these are setting the AppSettings
			//
			uint SharedRegionsSize = uint.Parse(ConfigurationSettings.AppSettings["SharedMemoryRegionSize"]);
			uint SharedRegions = uint.Parse(ConfigurationSettings.AppSettings["NumOfSharedMemoryRegions"]);
			if (SharedRegions > 0 && SharedRegionsSize > 0)
			{
				uint TotalPagesNeeded = (uint)(SharedRegions*SharedRegionsSize/CPU.pageSize);
				uint pagesPerRegion = TotalPagesNeeded/SharedRegions;

				// ForExample: 
				// I need 2 regions
				//	64 bytes needed for each
				//  4 pages each
				//  8 total pages needed

				// Because I pre-allocate shared memory I'll have the luxury of contigous pages of memory.
				// I'll exploit this hack in MapSharedMemoryToProcess
				foreach (MemoryPage page in _pageTable)
				{
					// Do we still need pages?
					if (TotalPagesNeeded > 0)
					{
						// If this page is assigned to the OS, take it
						if (page.SharedMemoryRegion == 0) 
						{
							// Now assign it to us
							page.SharedMemoryRegion = SharedRegions;
							TotalPagesNeeded--;
							if (TotalPagesNeeded % pagesPerRegion == 0) 
								SharedRegions--;
						}
					}
					else //We have all we need
						break;
				}
			}
		}


		/// <summary>
		/// 
		/// </summary>
		/// <param name="p">The Process</param>
		/// <param name="bytesRequested">The number of bytes requested.  Will be rounded up to the nearest page</param>
		/// <returns>The Start Address of the Alloc'ed memory</returns>
		public uint ProcessHeapAlloc(Process p, uint bytesRequested)
		{
			// Round up to the nearest page boundary
			uint pagesRequested = MemoryManager.BytesToPages(bytesRequested);
			uint addrStart = 0;

			//
			// Finds n *Contiguous* Pages
			//

			// Start with a list of potentialPages...
			ArrayList potentialPages =  new ArrayList();
			
			// Look through all the pages in our heap
			for (int i = 0; i < p.PCB.heapPageTable.Count; i++)
			{
				// The pages must be contiguous
				bool bContiguous = true;
				
				//From this start page, check for contiguous free pages nearby
				MemoryPage startPage = (MemoryPage)p.PCB.heapPageTable[i];

				//Is this page, and x ahead of it free?
				if (startPage.heapAllocationAddr == 0)
				{
					potentialPages.Clear();
					potentialPages.Add(startPage);

					//Is this page, and x ahead of it free?
					for (int j = 1; j < pagesRequested;j++)
					{
						// Have we walked past the end of the heap?
						if ((i+j) >= p.PCB.heapPageTable.Count)
							throw new HeapException(p.PCB.pid, pagesRequested*CPU.pageSize);

						MemoryPage nextPage = (MemoryPage)p.PCB.heapPageTable[i+j];
						if (nextPage.heapAllocationAddr == 0) 
							potentialPages.Add(nextPage);
						else
							bContiguous = false;
					}
					// If we make it here, we've found enough contiguous pages, break and continue
					if (bContiguous == true) 
						break;
				}
			}

			// Did we not find enough pages?
			if (potentialPages.Count != pagesRequested)
				throw new HeapException(p.PCB.pid, pagesRequested*CPU.pageSize);

			// Mark each page with the address of the original alloc 
			// so we can Free them later
			addrStart = ((MemoryPage)potentialPages[0]).addrProcessIndex;
			foreach (MemoryPage page in potentialPages)
				page.heapAllocationAddr = addrStart;

			return addrStart;
		}


		/// <summary>
		/// For debugging only.  The value used to "zero out" memory when doing a FreeMemory. 
		/// </summary>
		private static int memoryClearInt;

		/// <summary>
		/// Releases pages that were Alloc'ed from the Process's Heap
		/// </summary>
		/// <param name="p">The Processes</param>
		/// <param name="startAddr">The Process address that the allocation began at</param>
		/// <returns></returns>
		public uint ProcessHeapFree(Process p, uint startAddr)
		{
			uint pageCount = 0;
			foreach (MemoryPage page in p.PCB.heapPageTable)
			{
				if (page.heapAllocationAddr == startAddr)
				{
					page.heapAllocationAddr = 0;
					pageCount++;
				}
			}
			
			//
			// For Heap Debugging, uncomment this line, 
			// this incrementing value will be used to 
			// clear memory out when releasing heap blocks
			//
			//memoryClearInt++;
			
			memoryClearInt = 0;
			SetMemoryOfProcess(p.PCB.pid, startAddr, pageCount*CPU.pageSize, (byte)memoryClearInt);
			return 0;

		}

		/// <summary>
		/// Adds all the pages allocated to a Process's heap to a PCB specific table of memory pages
		/// </summary>
		/// <param name="p">The Process</param>
		public void CreateHeapTableForProcess(Process p)
		{
			foreach (MemoryPage page in _pageTable)
			{
				if (page.pidOwner == p.PCB.pid)
				{
					if (page.addrProcessIndex >= p.PCB.heapAddrStart && page.addrProcessIndex < p.PCB.heapAddrEnd)
					{
						p.PCB.heapPageTable.Add(page);
					}
				}
			}
		}


		/// <summary>
		/// Gets a 4 byte unsigned integer (typically an opCode param) from memory
		/// </summary>
		/// <param name="processid">The calling processid</param>
		/// <param name="processIndex">The address in memory from the Process's point of view</param>
		/// <returns></returns>
		public uint getUIntFrom(uint processid, uint processIndex)
		{
			return CPU.BytesToUInt(getBytesFrom(processid, processIndex, 4));
		}

		/// <summary>
		/// Sets a 4 byte unsigned integer (typically an opCode param) to memory
		/// </summary>
		/// <param name="processid">The calling processid</param>
		/// <param name="processIndex">The address in memory from the Process's point of view</param>
		/// <param name="avalue">The new value</param>
		public void setUIntAt(uint processid, uint processIndex, uint avalue)
		{
			setBytesAt(processid, processIndex, CPU.UIntToBytes(avalue));
		}

		/// <summary>
		/// Gets an array of "length" bytes from a specific process's memory address
		/// </summary>
		/// <param name="processid">The calling process's id</param>
		/// <param name="processIndex">The address in memory from the Process's point of view</param>
		/// <param name="length">how many bytes</param>
		/// <returns>an initialized byte array containing the contents of memory</returns>
		public byte[] getBytesFrom(uint processid, uint processIndex, uint length)
		{
			byte[] bytes = new byte[length];
			for (uint i = 0; i < length; i++)
			{
				bytes[i] = this[processid, processIndex + i];
			}
			return bytes;
		}

		/// <summary>
		/// Sets an array of bytes to a specific process's memory address
		/// </summary>
		/// <param name="processid">The calling processid</param>
		/// <param name="processIndex">The address in memory from the Process's point of view</param>
		/// <param name="pageValue">The source array of bytes</param>
		public void setBytesAt(uint processid, uint processIndex, byte[] pageValue)
		{
			for (uint i = 0; i < pageValue.Length; i++)
			{
				this[processid, processIndex+i] = pageValue[i];
			}
		}


	
		/// <summary>
		/// Translates a Process's address space into physical address space
		/// </summary>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -