Esempio n. 1
0
        /// <summary>
        /// Конструктор заточен под 32 бита и 4096 размер страниц
        /// </summary>
        /// <param name="bitDepth">разрядность</param>
        /// <param name="hardware">железо в машине</param>
        /// <param name="pageSize">размер страницы</param>
        public OS(int bitDepth, Hardware hardware, int pageSize)
        {
            PageMaxAge    = 70;
            this.PageSize = pageSize;
            BitDepth      = bitDepth;
            this.hardware = hardware;
            int freePageCount = 0;

            for (int i = 0; i < hardware.RamSlotsNumber; i++)
            {
                freePageCount += (hardware.RAMs[i].ByteCells.Length * 4) / pageSize; // число блоков по 32 бита * 4 = число байт. Поделим на размер страницы в байтах и получим число страниц
            }
            this.FreePages = new List <int>();
            for (int i = 0; i < freePageCount; i++)
            {
                FreePages.Add(i);
            }
            processes = new List <Process>();
            //
            // Создаю директорию в которой будут храниться текстовики для каждого процесса (один процесс = один файл)
            //

            Directory.CreateDirectory(Directory.GetCurrentDirectory() + "\\Processies");
            CurrentDirectoryName = Directory.GetCurrentDirectory() + "\\Processies";
        }
Esempio n. 2
0
        /// <summary>
        /// Получает ссылку на массив BitArray[] (физическая память) и смещение в этой памяти, с которого начинается свободный блок
        /// памяти размером в указанное количество страниц. В случае неудачи выкидывает исключение OutOfMemoryException.
        /// </summary>
        /// <param name="indexesInFreePageList">результат метода private int[] GetFreePageIndexesInListOfPages(int pageCount)</param>
        /// <param name="offset">начало блока размером в 32(64) бита</param>
        /// <returns></returns>
        private ref BitArray[] GetFreePages(int[] indexesInFreePageList, out uint offset)
        {
            uint firstPageAdress = (uint)FreePages[indexesInFreePageList[0]] * (uint)PageSize;

            offset = firstPageAdress / (uint)(bitDepth / 8);   // начало блока размером в 32(64) бита
            for (int i = 0; i < hardware.RAMs.Length; i++)
            {
                uint physicalEndAdress = hardware.RAMs[i].PhysicalAdress + (uint)(hardware.RAMs[i].ByteCells.Length * bitDepth / 8);
                if (firstPageAdress >= hardware.RAMs[i].PhysicalAdress && firstPageAdress < physicalEndAdress)
                {
                    uint lastPageAdress = (uint)FreePages[indexesInFreePageList[indexesInFreePageList.Length - 1]] * (uint)PageSize;
                    //
                    // это смежные блоки памяти, рсположенные на одной физической плашке
                    //
                    if (lastPageAdress >= hardware.RAMs[i].PhysicalAdress && lastPageAdress < physicalEndAdress)
                    {
                        for (int j = 0; j < indexesInFreePageList.Length; j++)
                        {
                            FreePages.RemoveAt(indexesInFreePageList[j]);
                        }
                        return(ref hardware.RAMs[i].ByteCells);
                    }
                }
            }
            throw new OutOfMemoryException("В физической памяти данные страницы находятся на разных физических модулях");
        }
Esempio n. 3
0
        /// <summary>
        /// "Убивает" процесс с указанным индексом в списке процессов
        /// </summary>
        /// <param name="processIndex"></param>
        public void KillProcess(int pid)
        {
            int processIndex = 0;

            for (int i = 0; i < processes.Count; i++)
            {
                if (processes[i].PID == pid)
                {
                    processIndex = i;
                    break;
                }
            }
            for (int i = 0; i < processes[processIndex].PageTable.Size; i++)
            {
                //
                // очистил страницы
                //
                uint adress = ConvertToRealPhysicalAdress(processes[processIndex].PageTable.PageTableEntries[i].Adress);
                RAM  ram    = AppropriatePhysicalRamBlock(adress);
                ClearPage(ref ram.ByteCells, ram.PhysicalAdress, adress);
                //
                // добавить в список свободных страниц
                //
                if (processes[processIndex].PageTable.PageTableEntries[i].Present)
                {
                    FreePages.Add(processes[processIndex].PageTable.PageTableEntries[i].Adress);
                }
            }
            // страницы, занимаемые таблицей тоже надо очистить
            uint realAdress = 0;

            for (int i = 0; i < hardware.RAMs.Length; i++)
            {
                bool isCorrect;
                realAdress = processes[processIndex].PageTable.GetRealPhysicalAdress(ref hardware.RAMs[i], out isCorrect);
                if (isCorrect)
                {
                    break;
                }
            }
            //
            // Тут по хорошему надо бы проверку на значение isCorrect, но не буду делать (посмотрим, что получится)
            //
            int pageCount = processes[processIndex].PageTable.Size * (bitDepth / 8) / PageSize;

            for (int i = 0; i < pageCount; i++)
            {
                int pageNumber = ConvertRealAdressToPageNumber(realAdress);
                FreePages.Add(pageNumber);
            }
            processes[processIndex].PageTable.Clear();

            FreePages.Sort();

            File.Delete(CurrentDirectoryName + "\\" + processes[processIndex].FileName);

            processes.RemoveAt(processIndex);
        }
Esempio n. 4
0
        /// <summary>
        /// Создает новый процесс
        /// </summary>
        /// <param name="memory">количество требуемой памяти в байтах</param>
        public void CreateNewProcess(string name, int memory, int prioryty)
        {
            int pid = 0;

            // вычислить размер таблицы - количество страниц для храненния таблицы
            int pageCountForTable = PageNumberForTable(memory * 2);

            try
            {
                BitArray[] bits      = GetFreePages(GetFreePageIndexesInListOfPages(pageCountForTable), out uint offset);
                PageTable  pageTable = new PageTable(offset, ref bits, pageCountForTable);
                pid = CreateRandomPid();
                //
                // инициализировать таблицу страниц
                //
                int pageCountToInit = memory / PageSize;
                if (FreePages.Count >= pageCountToInit)
                {
                    for (int i = 0; i < pageCountToInit; i++)
                    {
                        pageTable.PageTableEntries[i].Adress  = FreePages[0];
                        pageTable.PageTableEntries[i].Present = true;
                        FreePages.RemoveAt(0);
                    }
                }
                else
                {
                    throw new OutOfMemoryException("Невозможно выделить минимум памяти процессу");
                }
                processes.Add(new Process(name, memory, pid, prioryty, ref pageTable));
                //
                // создать файл на диске, отвечающий за данный процесс
                //
                //File.Create(CurrentDirectoryName + processes[processes.Count - 1].Name + ".prc");
                StreamWriter writer      = new StreamWriter(CurrentDirectoryName + "\\" + processes[processes.Count - 1].FileName);
                int          recordCount = processes[processes.Count - 1].WSClockEntryMirrors.Count;
                for (int i = 0; i < recordCount; i++)
                {
                    WritePageToDrive(writer, processes[processes.Count - 1].PageTable.PageTableEntries[i], i);
                    processes[processes.Count - 1].WSClockEntryMirrors[i].WrittenIntoFile = true;
                }
                writer.Close();
            }
            catch (OutOfMemoryException e)
            {
                MessageBox.Show(e.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            catch (Exception)
            {
                MessageBox.Show("Произошло что-то непредвиденное", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Обрабатывает исключение PageFault алгоритмом WSClock. доработать, не использовать
        /// </summary>
        /// <param name="process">процесс, вызвавший ошибку</param>
        /// <param name="pageNumber">номер страницы в таблице страниц, обращение к которой вызвало ошибку</param>
        public void PageFaultExeptionHandler(Process process, int pageNumber)
        {
            bool memoryAllocated = false;

            if (process.PageTable.PageTableEntries[pageNumber].Adress == 0)
            {
                if (FreePages.Count > 0)
                {
                    process.PageTable.PageTableEntries[pageNumber].Present = true;
                    process.PageTable.PageTableEntries[pageNumber].Adress  = FreePages[0];
                    FreePages.RemoveAt(0);
                    process.WSClockEntryMirrors.Add(new WSClockEntryMirror(ref process.PageTable.PageTableEntries[pageNumber], process.CurrentVirtualTime, pageNumber));
                    memoryAllocated = true;
                    StreamWriter writer = new StreamWriter(CurrentDirectoryName + "\\" + process.FileName, true);
                    WritePageToDrive(writer, process.PageTable.PageTableEntries[pageNumber], pageNumber);
                    writer.Close();
                }
            }

            if (!memoryAllocated)
            {
                bool       ableToRemove          = false;
                List <int> removalCandidates     = new List <int>();
                int        removalPage           = 0;
                int        removalPageIndex      = 0;
                int        workingSetPagesNumber = process.WSClockEntryMirrors.Count;
                for (int i = 0; i < workingSetPagesNumber; i++)
                {
                    if (!ableToRemove)
                    {
                        if (process.WSClockEntryMirrors[i].PageTableEntryIndex == pageNumber)   // то такую страницу в расчет не берем, т.к. к ней и обратились
                        {
                            process.WSClockEntryMirrors[i].Referenced  = false;
                            process.WSClockEntryMirrors[i].LastUseTime = process.CurrentVirtualTime;
                            //continue;
                        }
                        else if (process.WSClockEntryMirrors[i].Referenced == true)
                        {
                            process.WSClockEntryMirrors[i].Referenced  = false;
                            process.WSClockEntryMirrors[i].LastUseTime = process.CurrentVirtualTime;
                        }
                        else if ((process.CurrentVirtualTime - process.WSClockEntryMirrors[i].LastUseTime) <= PageMaxAge) // это еще рабочий набор
                        {
                            removalCandidates.Add(i);
                        }
                        else  // можно удалить
                        {
                            ableToRemove     = true;
                            removalPage      = process.WSClockEntryMirrors[i].PageTableEntryIndex;
                            removalPageIndex = i;
                            break;
                        }
                    }
                    else if (process.WSClockEntryMirrors[i].Referenced == true)
                    {
                        process.WSClockEntryMirrors[i].Referenced  = false;
                        process.WSClockEntryMirrors[i].LastUseTime = process.CurrentVirtualTime;
                    }
                }
                if (!ableToRemove)
                {
                    if (removalCandidates.Count == 0)
                    {
                        Random random = new Random();
                        do
                        {
                            removalPageIndex = random.Next(0, process.WSClockEntryMirrors.Count - 1);
                            removalPage      = process.WSClockEntryMirrors[removalPageIndex].PageTableEntryIndex;
                        } while (removalPage == pageNumber);
                    }
                    else
                    {
                        for (int i = 0; i < removalCandidates.Count; i++)
                        {
                            if (!process.WSClockEntryMirrors[removalCandidates[i]].Modified)
                            {
                                ableToRemove     = true;
                                removalPage      = process.WSClockEntryMirrors[removalCandidates[i]].PageTableEntryIndex;
                                removalPageIndex = removalCandidates[i];
                                break;
                            }
                        }
                        if (!ableToRemove)
                        {
                            removalPage      = process.WSClockEntryMirrors[removalCandidates[0]].PageTableEntryIndex;
                            removalPageIndex = removalCandidates[0];
                        }
                    }
                }
                // если страница модифицирована, то ее данные нужно перезаписать на диск
                if (process.WSClockEntryMirrors[removalPageIndex].Modified == true)
                {
                    // если страница записана на диск - обновляем данные
                    if (process.WSClockEntryMirrors[removalPageIndex].WrittenIntoFile)
                    {
                        if (!WritePageToDrive(process.FileName, process.WSClockEntryMirrors[removalPageIndex].PageTableEntry, process.WSClockEntryMirrors[removalPageIndex].PageTableEntryIndex, true))
                        {
                            throw new Exception("Дисковая операция с процессом крашнулась");
                        }
                    }
                    else  // иначе просто пишем в файл
                    {
                        StreamWriter writer = new StreamWriter(CurrentDirectoryName + "\\" + process.FileName, true);
                        WritePageToDrive(writer, process.WSClockEntryMirrors[removalPageIndex].PageTableEntry, process.WSClockEntryMirrors[removalPageIndex].PageTableEntryIndex);
                        process.WSClockEntryMirrors[removalPageIndex].WrittenIntoFile = true;
                        writer.Close();
                    }
                }
                // в записи "удаляемой" страницы выставляем бит отображения в 0. Больше с этой записью ничего делать не надо
                process.PageTable.PageTableEntries[process.WSClockEntryMirrors[removalPageIndex].PageTableEntryIndex].Present = false;

                // В ту запись (номер в таблице страниц), обращение к которой вызвало ошибку нужно записать адрес "удаленной страницы"
                // Удаляемую страницу нужно записать на диск, если нужно, и в таблице страниц выставить бит отображения в 0
                int oldAdress = process.PageTable.PageTableEntries[pageNumber].Adress;

                // вычисляем физическое местоположение страницы, в которую будем писать новые данные
                uint adress         = (uint)process.PageTable.PageTableEntries[removalPageIndex].Adress * (uint)PageSize;
                int  ramBlockNumber = 0;
                for (int j = 0; j < hardware.RAMs.Length; j++)
                {
                    uint endPhysicalAdress = hardware.RAMs[j].PhysicalAdress + (uint)(hardware.RAMs[j].ByteCells.Length * (bitDepth / 8));
                    if (adress >= hardware.RAMs[j].PhysicalAdress && adress < endPhysicalAdress)
                    {
                        ramBlockNumber = j;
                        break;
                    }
                }
                // начало страницы
                int startBitArrayBlock = (int)(adress - hardware.RAMs[ramBlockNumber].PhysicalAdress) / (bitDepth / 8);
                // если не удалось восстановить (нет на диске)
                if (!RestoreProcessPage(ref process, pageNumber, ref hardware.RAMs[ramBlockNumber].ByteCells, startBitArrayBlock, adress))
                {
                    MessageBox.Show("Данные поцесса на диске не найдены. Процесс будет убит.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    KillProcess(process.PID);
                }
                else
                {
                    process.PageTable.PageTableEntries[pageNumber].Present = true;
                    // костыль, но так нужно, чтобы адрес "удаляемой" страницы не был забыт
                    process.PageTable.PageTableEntries[process.WSClockEntryMirrors[removalPageIndex].PageTableEntryIndex].Adress = oldAdress;
                }
            }
        }