Сделай Сам Свою Работу на 5

Программная реализация системы





Библиотека функций dll описывается в файле control.cpp. Ниже приведено содержимое файла.

 

 

#include "baseFuncErr.h"

#include "control.h"

ManageProc *Process;

ManageMem *RAM;

ManageIO *HD;

HANDLE IOEvent = CreateEvent (NULL, false, true, "EventWriting");

 

//----------------------------------------------------------------

void FlowWrite (void *Param)

{

char log[256];

STdisk *Data = (STdisk*)Param;

 

WaitForSingleObject (IOEvent, INFINITE);

ResetEvent(IOEvent);

 

// если выполняет система, то она помещает Своп таблицу на Диск

if (Data->DataType == 255)

{

// очищение DataPage

BYTE *Empty = new BYTE[SIZE_CLUSTER];

memset(Empty, 0, SIZE_CLUSTER);

WriteMemoryEx(Data->AdrMem, Empty, SIZE_CLUSTER);

delete(Empty);

 

WriteMemoryEx(Data->AdrMem, Data->Buffer, sizeof(VirtPages) * Data->Size);

}

 

WriteDiskEx(Data->AdrMem, Data->Sector);

 

if (Data->nProc < COUNT_PROCESS)

{

dCript *desCriptor = new dCript();

// получаем из виртуальной машины таблицу процессов

ReadMemoryEx(Data->TableProc + sizeof(dCript) * Data->nProc, (BYTE*)desCriptor, sizeof(dCript));

if (desCriptor->status != NotExist)

desCriptor->status = Ready;

WriteMemoryEx(Data->TableProc + sizeof(dCript) * Data->nProc, (BYTE*)desCriptor, sizeof(dCript));

}

SetEvent(IOEvent);

_endthread();

}

 

void FlowRead (void *Param)

{

STdisk *Data = (STdisk*)Param;

 

WaitForSingleObject (IOEvent, INFINITE);

ResetEvent(IOEvent);

 

ReadDisk (Data->AdrMem, Data->Sector);

 

if (Data->nProc < COUNT_PROCESS)

{

dCript *desCriptor = new dCript();

// получаем из виртуальной машины таблицу процессов



ReadMemoryEx(Data->TableProc + sizeof(dCript) * Data->nProc, (BYTE*)desCriptor, sizeof(dCript));

desCriptor->status = Ready;

WriteMemoryEx(Data->TableProc + sizeof(dCript) * Data->nProc, (BYTE*)desCriptor, sizeof(dCript));

}

 

SetEvent (IOEvent);

_endthread();

}

 

int WriteExternFile (char * fileName, BYTE * lpBuffer, int count, int nProcess);

 

void TreadWriteFile (void* lpParam)

{

char log[256];

STdisk *Data = (STdisk*)lpParam;

 

int count = Data->count;

int offset = Data->offset;

 

WaitForSingleObject (IOEvent, INFINITE);

ResetEvent(IOEvent);

 

sprintf(log, "Начат поток записи данных из адресного пространства процесса в файл, поток запущен процессом %d\r\n", Data->nProc);

AddLog(log);

 

WORD *Index = new WORD[COUNT_IN];

// читаем таблицу индексов

ReadMemoryEx(Data->TableIN, (BYTE*)Index, sizeof(WORD) * COUNT_IN);

 

dCript *Proc = new dCript();

// получаем из виртуальной машины дескриптор процесса

ReadMemoryEx(Data->TableProc + sizeof(dCript) * Data->nProc, (BYTE*)Proc, sizeof(dCript));

 

// Чтение таблицы страниц процесса

VirtPages *Virt = new VirtPages[Proc->countPage]();

ReadMemory (Proc->tableVirt * SIZE_PAGE, (BYTE*)Virt, sizeof(VirtPages) * Proc->countPage);

 

BYTE *TableParts = new BYTE[10];

ReadMemory (RAM->TableParts + Data->nProc*10, TableParts, 10);

 

int CountPart = 0;

int *nPage = new int[10];

for (int i=1, sub=0; i < 10; i++)



{

if (TableParts[i] == 0)

{

nPage[CountPart] = Proc->countPage - sub;

CountPart++;

break;

}

else

{

nPage[CountPart] = TableParts[i] - sub;

sub += nPage[CountPart];

CountPart++;

}

}

AddLog("Копирование модифицированных страниц в файл подкачки\r\n");

// копируем модифицированные страницы в файл подкачки

for (int i=0, sub=0; i < CountPart; i++)

{

if (i != 0)

{

sub += nPage[i-1];

}

for (int j=0; j < nPage[i]; j++)

{

if (Virt[j + sub].Sign & 0x04)

{

int PageInSwap = RAM->SearchSwapPage(Data->nProc, j, i);

WriteDiskEx(Virt[j + sub].NumPhysPage * SIZE_PAGE, PageInSwap);

}

}

}

AddLog("Завершено копирование модифицированных страниц в файл подкачки\r\n");

 

// определям страницу с которой необходимо начать писать данные в файл

int FirstPage = Data->firstByte / SIZE_PAGE;

// смещение в странице

int PageOffset = Data->firstByte % SIZE_PAGE;

// вычисляем количество страниц которые необходимо прочитать

int CountPage = Data->count / SIZE_PAGE;

if (Data->count % SIZE_PAGE != 0)

CountPage++;

if (PageOffset != 0)

CountPage++;

 

AddLog("Чтение адресного пространства процесса в буффер\r\n");

BYTE *ProcessBuffer = new BYTE[CountPage * SIZE_PAGE];

 

for (int i=Data->NumPart, k=0; i < CountPart; i++)

{

int sub = 0;

for (int s=0; s < i; s++)

sub += nPage[s];

 

int j=0;

if (i == Data->NumPart)

j = FirstPage;

 

for (; j < nPage[i]; j++)

{

int PageInSwap = RAM->SearchSwapPage(Data->nProc, j, i);

ReadDiskEx(Data->DataPage, PageInSwap);

ReadMemoryEx(Data->DataPage, ProcessBuffer + k*SIZE_PAGE, SIZE_PAGE);

k++;

CountPage--;

if (CountPage == 0)

break;

}

if (CountPage == 0)

break;

}

AddLog("Завершено чтение адресного пространства процесса в буффер\r\n");

 

sFile *File = new sFile();

// ищем файл с таким именем

int Num = HD->FindFile(Data->FileName);

// если находим такой файл

if (Num >= 0)

{

// читаем запись о файле

ReadMemory(RAM->TableFile + sizeof(sFile)*Num, (BYTE*)File, sizeof(sFile));

 

int newSize = (count + offset) - File->fileSize;

// если смещение + размер записываемых данных не умещается в уже зарезервированное место



if (newSize > 0)

{

int HaveSize = File->fileSize / SIZE_CLUSTER;

if (File->fileSize % SIZE_CLUSTER != 0)

HaveSize++;

File->fileSize = File->fileSize + abs(newSize);

// количество секторов которые нужно выделить дополнительно

newSize = (File->fileSize / SIZE_CLUSTER) + 1 - HaveSize;

 

int Last = HD->GetSector(File->firstCluster, COUNT_IN);

HD->ReservSpace (newSize, Last);

// обновляем информацию о файле

WriteMemory (RAM->TableFile + sizeof(sFile)*Num, (BYTE*)File, sizeof(sFile));

// читаем таблицу индексов

ReadMemoryEx(Data->TableIN, (BYTE*)Index, sizeof(WORD) * COUNT_IN);

}

 

// Получаем номер сектора в который будем писать

int Sector = HD->GetSector(File->firstCluster, offset / SIZE_CLUSTER);

// вычисляем размер временного буффера в секторах

int SizeBuffer = count / SIZE_CLUSTER;

if (count % SIZE_CLUSTER != 0)

SizeBuffer++;

// вычисляем смещение в секторе

int sub = offset - (offset / SIZE_CLUSTER) * SIZE_CLUSTER;

// если смещение не кратно сектору, т.е. информацию придется начинать писать не с начала сектора

if (sub + count > SIZE_CLUSTER)

SizeBuffer++;

 

BYTE *Buffer = new BYTE[SizeBuffer * SIZE_PAGE];

 

WORD Current = Sector;

int read = 0;

// вычислим количество секторов которые необходимо прочитать

int count = SizeBuffer;

do

{

int size = SizeBuffer * SIZE_PAGE - read;

if (size > SIZE_CLUSTER-2)

size = SIZE_CLUSTER-2;

 

ReadDiskEx(Data->DataPage, Current);

ReadMemoryEx(Data->DataPage, Buffer + read, size);

read += size;

 

Current = Index[Current];

count--;

}

while (Current < COUNT_IN && count > 0);

 

// копируем данные процесса в буффер данных файла

memcpy (Buffer + sub, ProcessBuffer + PageOffset, Data->count);

 

// записываем данные

 

BYTE *Empty = new BYTE[SIZE_CLUSTER];

memset(Empty, 0, SIZE_CLUSTER);

 

Current = Sector;

 

int write = 0;

do

{

// вычисляем оставшийся размер для записи

int size = SizeBuffer*SIZE_PAGE - write;

// пишем размером не больше секора

if (size > SIZE_CLUSTER-2)

size = SIZE_CLUSTER-2;

 

// очищение DataPage

WriteMemoryEx(Data->DataPage, Empty, SIZE_CLUSTER);

// формируем страницу данных для записи на диск

WriteMemoryEx(Data->DataPage, Buffer + write, size);

 

WriteDiskEx(Data->DataPage, Current);

 

write += size;

// переходим на следующий сектор

Current = Index[Current];

}

while (Current < COUNT_IN && SizeBuffer*SIZE_PAGE != write);

 

// после завершения записи возвращаем процесс в готовность

if (Data->nProc < COUNT_PROCESS)

{

dCript *desCriptor = new dCript();

// получаем из виртуальной машины таблицу процессов

ReadMemoryEx(Data->TableProc + sizeof(dCript) * Data->nProc, (BYTE*)desCriptor, sizeof(dCript));

if (desCriptor->status != NotExist)

desCriptor->status = Ready;

AddLog("Процесс переводится в готовность\r\n");

WriteMemoryEx(Data->TableProc + sizeof(dCript) * Data->nProc, (BYTE*)desCriptor, sizeof(dCript));

delete(desCriptor);

}

 

sprintf(log, "Завершен поток записи данных из адресного пространства процесса в файл, поток запущен процессом %d\r\n", Data->nProc);

AddLog(log);

}

else

{

BYTE *BufferForWrite = new BYTE[Data->count + Data->offset];

memset(BufferForWrite, 0, Data->count + Data->offset);

memcpy(BufferForWrite + Data->offset, ProcessBuffer, Data->count);

WriteExternFile(Data->FileName, BufferForWrite, Data->count + Data->offset, Data->nProc);

}

SetEvent (IOEvent);

_endthread();

}

 

void TreadReadFile (void* lpParam)

{

char log[256];

STdisk *Data = (STdisk*)lpParam;

 

WaitForSingleObject (IOEvent, INFINITE);

ResetEvent(IOEvent);

 

sprintf(log, "Начат поток чтения данных в адресное пространство процесса из файла, поток запущен процессом %d\r\n", Data->nProc);

AddLog(log);

 

WORD *Index = new WORD[COUNT_IN];

// читаем таблицу индексов

ReadMemoryEx(Data->TableIN, (BYTE*)Index, sizeof(WORD) * COUNT_IN);

 

dCript *Proc = new dCript();

// получаем из виртуальной машины дескриптор процесса

ReadMemoryEx(Data->TableProc + sizeof(dCript) * Data->nProc, (BYTE*)Proc, sizeof(dCript));

 

// Чтение таблицы страниц процесса

VirtPages *Virt = new VirtPages[Proc->countPage]();

ReadMemory (Proc->tableVirt * SIZE_PAGE, (BYTE*)Virt, sizeof(VirtPages) * Proc->countPage);

 

BYTE *TableParts = new BYTE[10];

ReadMemoryEx(RAM->TableParts + Data->nProc*10, TableParts, 10);

 

int CountPart = 0;

int *nPage = new int[10];

for (int i=1, sub=0; i < 10; i++)

{

if (TableParts[i] == 0)

{

nPage[CountPart] = Proc->countPage - sub;

CountPart++;

break;

}

else

{

nPage[CountPart] = TableParts[i] - sub;

sub += nPage[CountPart];

CountPart++;

}

}

 

BYTE *Buffer = new BYTE[Data->Size];

 

WORD Current = Data->Sector;

int read = 0;

// вычислим количество секторов которые необходимо прочитать

int count = Data->Size / SIZE_CLUSTER;

if (Data->Size % SIZE_CLUSTER != 0)

count++;

do

{

int size = Data->Size - read;

if (size > SIZE_CLUSTER-2)

size = SIZE_CLUSTER-2;

 

ReadDiskEx(Data->DataPage, Current);

ReadMemoryEx(Data->DataPage, Buffer + read, size);

read += size;

 

Current = Index[Current];

count--;

}

while (Current < COUNT_IN && count > 0);

 

// обрезаем данные согласно смещению в секторе

BYTE *cutBuffer = new BYTE[Data->Size];

memcpy (cutBuffer, Buffer + Data->offset, read - Data->offset);

// обновляем данные буффера

memset (Buffer, 0, Data->Size);

memcpy (Buffer, cutBuffer, read - Data->offset);

 

// определям страницу с которой необходимо начать писать данные в файл

int FirstPage = Data->firstByte / SIZE_PAGE;

// смещение в странице

int PageOffset = Data->firstByte % SIZE_PAGE;

// вычисляем количество страниц которые необходимо прочитать

int CountPage = Data->count / SIZE_PAGE;

if (Data->count % SIZE_PAGE != 0)

CountPage++;

if (PageOffset != 0)

CountPage++;

 

 

AddLog("Запись данных файла в адресное пространство процесса\r\n");

for (int i=Data->NumPart, k=0; i < CountPart; i++)

{

int offset = 0;

for (int s=0; s < i; s++)

offset += nPage[s];

 

int j=0;

if (i == Data->NumPart)

j = FirstPage;

 

for (; j < nPage[i]; j++)

{

int PageInSwap = RAM->SearchSwapPage(Data->nProc, j, i);

WriteMemoryEx(Data->DataPage, Buffer + k*SIZE_PAGE, SIZE_PAGE);

WriteDiskEx(Data->DataPage, PageInSwap);

CountPage--;

k++;

if (CountPage == 0)

break;

}

if (CountPage == 0)

break;

}

AddLog("Завершена запись данных файла в адресное пространство процесса\r\n");

 

 

AddLog("Копирование данных процесса из файла подкачки в страницы в ОП\r\n");

// копируем модифицированные страницы в файл подкачки

for (int i=0, k=0; i < CountPart; i++, k++)

{

int offset = 0;

for (int s=0; s < i; s++)

offset += nPage[s];

 

for (int j=0; j < nPage[i]; j++)

{

if (Virt[j + offset].Sign & 0x01)

{

int PageInSwap = RAM->SearchSwapPage(Data->nProc, j, i);

ReadDiskEx(Virt[j + offset].NumPhysPage * SIZE_PAGE, PageInSwap);

Virt[i].SetUpdating(false);

}

}

}

AddLog("Завершено копирование данных процесса из файла подкачки в страницы в ОП\r\n");

 

// после завершения записи возвращаем процесс в готовность

if (Data->nProc < COUNT_PROCESS)

{

dCript *desCriptor = new dCript();

// получаем из виртуальной машины таблицу процессов

ReadMemoryEx(Data->TableProc + sizeof(dCript) * Data->nProc, (BYTE*)desCriptor, sizeof(dCript));

if (desCriptor->status != NotExist)

desCriptor->status = Ready;

AddLog("Процесс переводится в готовность\r\n");

WriteMemoryEx(Data->TableProc + sizeof(dCript) * Data->nProc, (BYTE*)desCriptor, sizeof(dCript));

delete(desCriptor);

}

 

sprintf(log, "Завершен поток чтения данных в адресное пространство процесса из файла, поток запущен процессом %d\r\n", Data->nProc);

AddLog(log);

 

SetEvent (IOEvent);

_endthread();

}

 

 

//-------------------------------------------------------------

// методы для получения текущего состояние машины

//-------------------------------------------------------------

 

// запуск подсистем управления

DLLFUNC void Start() {

AddLog("Start\r\n");

 

AddLog("Инициализация оперативной памяти\r\n");

RAM = new ManageMem();

 

AddLog("Инициализация ЖД\r\n");

HD = new ManageIO(RAM->TableFile, RAM->TableIN, RAM->DataPage, RAM->TableSwap);

 

AddLog("Инициализация подсистемы управления процессами\r\n");

Process = new ManageProc(RAM->TableProc);

AddLog("Начинаем работу\r\n");

}

 

// остановка подсистем управления

DLLFUNC void Stop() {

AddLog("Stop\r\nПрекращаем работу\r\n");

 

 

}

 

 

//enum eProcessStatus = { NotExist = 0, Execute = 1, Ready = 2, Wait = 3};

 

// получить информацию о процессах в системе

// размер буфера = 100

// lpProcStatusBuffer - буфер для сохранения информации о статусе процесса

// lpProcData - буфер для сохранения дополнительной информации о процессе

// 1. Гарантированное планирование - номер пользователя от имени которого запущен процесс

// 2. SJF с предсказанием - текущая оценка процесса

// 3. Вытесняющий SJF - оставшееся время выполнения процесса

// 4. Приоритетное планирование с абсолютным приоритетом - номер приоритета

// 5. Многоуровневая очередь - номер приоритета

DLLFUNC void GetProcessStatus(BYTE * lpProcStatusBuffer, unsigned int * lpProcData) {

 

// выставляем статусы процессам

Process->SelectActiv();

 

dCript *desCriptors = new dCript[COUNT_PROCESS]();

// получаем из виртуальной машины таблицу процессов

ReadMemory(Process->TableProc, (BYTE*)desCriptors, sizeof(dCript)*COUNT_PROCESS);

 

// наполнение буфера дополнительной информации процессов

double *buffer1 = new double[COUNT_PROCESS];

for (int i=0; i<COUNT_PROCESS; i++)

buffer1[i] = desCriptors[i].procData;

memcpy (lpProcData, buffer1, COUNT_PROCESS);

delete(buffer1);

 

// наполнение буфера статусов процессов

BYTE *buffer2 = new BYTE[COUNT_PROCESS];

for (int i=0; i<COUNT_PROCESS; i++)

buffer2[i] = desCriptors[i].status;

memcpy (lpProcStatusBuffer, buffer2, COUNT_PROCESS);

delete(buffer2);

 

delete(desCriptors);

}

 

//----------------------------------------

 

// получить количество блоков

DLLFUNC int GetPhysMemoryBlockCount() {

 

return GetMemorySize()/SIZE_PAGE;

}

 

// получить описание блоков

// lpBlockList - список описания блоков

DLLFUNC void GetPhysMemoryBlockList(PHYS_MEMORY_BLOCK * lpBlockList) {

 

// количество блоков не должно превышать число, возращаемое функцией GetPhysMemoryBlockCount

PhysPages *TablePhysPages = new PhysPages[COUNT_PAGES]();

ReadMemory(RAM->TablePage, (BYTE*)TablePhysPages, sizeof(PhysPages) * COUNT_PAGES);

 

PHYS_MEMORY_BLOCK *buffer = new PHYS_MEMORY_BLOCK[COUNT_PAGES]();

 

int k=0;

for (int i=0; i<COUNT_PAGES; i++)

{

if (TablePhysPages[i].NumProc != 254)

{

buffer[i].nProcess = TablePhysPages[i].NumProc;

buffer[i].nStart = i * SIZE_PAGE;

buffer[i].nLength = SIZE_PAGE;

}

else

{

buffer[i].nLength = 0;

buffer[i].nProcess = 0;

buffer[i].nStart = 0;

}

}

 

memcpy (lpBlockList, buffer, sizeof(PHYS_MEMORY_BLOCK) * COUNT_PAGES);

delete(buffer);

delete(TablePhysPages);

}

 

//----------------------------------------

 

// получить информацию о состоянии диска посекторно

// 0 - свободный сектор

// 1-100 - сектор принадлежит файлу (номер совпадает с номером в каталоге)

// 255 - зарезервировано системой

DLLFUNC void GetDiskStatus(BYTE * lpStatusBuffer) {

 

char log[256];

// очищаем буфер

memset (lpStatusBuffer, 0, COUNT_IN);

 

sFile *File = new sFile[COUNT_FILE]();

// читаем таблицу файлов из оперативной памяти виртуальной машины

ReadMemory (HD->TableFile, (BYTE*)File, sizeof(sFile) * COUNT_FILE);

 

WORD *Index = new WORD[COUNT_IN];

// читаем таблицу индексов из оперативной памяти виртуальной машины

ReadMemory (HD->TableIN, (BYTE*)Index, sizeof(WORD) * COUNT_IN);

 

// место зарезервированное файлов подгрузки

for (int i=0; i < COUNT_PAGES*2; i++)

lpStatusBuffer[i] = 255;

 

// Просматриваем таблицу файлов

for (int i=0; i<COUNT_FILE; i++)

{

// если запись таблицы не пуста

if (File[i].firstCluster != COUNT_IN + 1)

{

// перебираем индексы файла пока не встретится последний

for (int j=File[i].firstCluster; j != COUNT_IN + 2; j = Index[j])

{

lpStatusBuffer[j] = i + 1;

}

}

}

 

delete(Index);

delete(File);

}

 

// получить каталог

// файлов на диске не более 100 (индексы с 1 по 100 включительно)

// имя файла не более 20 символов

DLLFUNC void GetDiskCatalog(char lpFileNames[][20], int * lpFirstSectors, int * lpSizes){

 

// читаем таблицу файлов

sFile *File = new sFile[COUNT_FILE]();

ReadMemory (HD->TableFile, (BYTE*)File, sizeof(sFile) * COUNT_FILE);

 

for (int i=0; i < COUNT_FILE; i++)

{

if (File[i].firstCluster != COUNT_IN + 1)

{

memcpy (lpFileNames[i+1], File[i].fileName, 20);

lpFirstSectors[i+1] = File[i].firstCluster;

lpSizes[i+1] = File[i].fileSize;

}

}

delete(File);

}

 

 

//-------------------------------------------------------------

// методы для подсистемы управления процессами

//-------------------------------------------------------------

 

// создать процесс

// nData - дополнительные параметры для процесса (зависит от алгоритма планирования)

// 1. Гарантированное планирование - номер пользователя от имени которого запущен процесс

// 2. SJF с предсказанием - не используется

// 3. Вытесняющий SJF - полное время выполнения процесса

// 4. Приоритетное планирование с абсолютным приоритетом - номер приоритета

// 5. Многоуровневая очередь (2 уровня: высокий приоритет – Round robin, низкий приоритет – FCFS) - номер приоритета

// функция должна вернуть номер для созданного процесса

DLLFUNC int osCreateProcess(int nData) {

 

int Num = Process->CreateProcess(nData);

 

return Num;

}

 

 

// удалить процесс с указанным номером

DLLFUNC void osDeleteProcess(int nProcess) {

char log[256];

dCript *desCriptor = new dCript();

// получаем дескриптор процесса

ReadMemory(Process->TableProc + sizeof(dCript)*nProcess, (BYTE*)desCriptor, sizeof(dCript));

// если таблица в ОП

if (desCriptor->sign == 1)

{

RAM->DeleteTablePage(desCriptor->tableVirt, desCriptor->countPage, 1);

}

RAM->CleanSwapProc(nProcess);

delete(desCriptor);

// удаляем дескриптор процесса

Process->DeleteProcess(nProcess);

}

 

// пустая команда для процесса

// команда без обращения к памяти и диску

DLLFUNC void osMakeEmptyCommand(int nProcess) {

}

 

 

//-------------------------------------------------------------

// методы для подсистемы управления памятью

//-------------------------------------------------------------

struct sSwap

{

WORD nSector; // из какого сектора ЖД копируем информацию

BYTE nProcess; // страницу какого процесса перемещаем в ОП

BYTE nPage; // какую страницу процесса перемещаем в ОП

BYTE nPart; //раздел страниц

};

 

int Swaping (int nProcess, int nPage, int nPart, int nSector)

{

AddLog ("Запущен поток Свопинг\r\n");

 

char log[256];

sprintf (log, "Запрос на перемещение виртуальной страницы %d, находящейся в секторе %d ЖД, процесса %d.\r\n", nPage, nSector, nProcess);

AddLog (log);

 

// читаем таблицу физических страниц

PhysPages *Table = new PhysPages[COUNT_PAGES]();

ReadMemory (RAM->TablePage, (BYTE*)Table, sizeof(PhysPages)*COUNT_PAGES);

 

// читаем дескриптор процесса, запросивший загрузку своей страницы в ОП

dCript *MovingProcess = new dCript();

ReadMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)MovingProcess, sizeof(dCript));

 

// Информация для потока чтения данных с диска

STdisk *ReadInfo = new STdisk;

ReadInfo->Sector = nSector;

ReadInfo->TableProc = Process->TableProc;

ReadInfo->nProc = nProcess;

 

AddLog ("Попытка найти свободную страницу в ОП для размещания требуемой\r\n");

// сначала пытаемся найти свободное место для загружаемой страницы

for (int i=0; i < COUNT_PAGES; i++)

if (Table[i].NumProc == 254)

{

AddLog ("Найдена свободная страница. Копирование...\r\n");

ReadInfo->AdrMem = i * SIZE_PAGE;

if ((HANDLE) _beginthread (FlowRead, 4096, ReadInfo) == INVALID_HANDLE_VALUE)

AddLog ("Поток чтения с диска запустить не удалось");

 

// обновление таблицы физических страниц

PhysPages *newPage = new PhysPages();

newPage->NumProc = nProcess;

newPage->NumVirtPage = nPage;

newPage->NumPart = nPart;

 

WriteMemory (RAM->TablePage + sizeof(PhysPages)*i, (BYTE*)newPage, sizeof(PhysPages));

delete(newPage);

 

delete(MovingProcess);

delete(Table);

AddLog ("Страница перемещена\r\n");

return i;

}

 

AddLog ("Вымещение страницы наихудшего процесса.\r\n");

// читаем дескриптор "наихудшего" процесса

dCript *Proc = new dCript();

ReadMemory (RAM->TableProc + sizeof(dCript)*Process->Badest, (BYTE*)Proc, sizeof(dCript));

 

// читаем таблицу страниц процесса

VirtPages *PartTable = new VirtPages[Proc->countPage]();

ReadMemory (Proc->tableVirt * SIZE_PAGE, (BYTE*)PartTable, sizeof(VirtPages) * Proc->countPage);

 

int MovingPage = -1;

// просматриваем таблицу страниц процесса

for (int i=0; i < Proc->countPage; i++)

{

if (PartTable[i].Sign & 0x01)

{

MovingPage = i;

break;

}

}

 

int SwapPage;

int Adress;

if (MovingPage >= 0)

{

sprintf (log, "Вымещается страница №%d, процесса %d\r\n", Table[PartTable[MovingPage].NumPhysPage].NumVirtPage, Process->Badest);

AddLog(log);

Adress = PartTable[MovingPage].NumPhysPage;

// ищем копию страницы в файле подкачки

SwapPage = RAM->SearchSwapPage(Process->Badest, Table[PartTable[MovingPage].NumPhysPage].NumVirtPage, PartTable[MovingPage].NumPart);

// если страница модифицирована, её следует копировать в Своп

if (PartTable[MovingPage].Sign & 0x04)

{

AddLog ("Вымещаемая страница модифицирована. Копируем её на ЖД\r\n");

// копирование на ЖД

STdisk *WriteInfo = new STdisk;

WriteInfo->AdrMem = PartTable[MovingPage].NumPhysPage * SIZE_PAGE;

WriteInfo->Sector = SwapPage;

WriteInfo->nProc = 255;

WriteInfo->DataType = 0;

WriteInfo->TableProc = Process->TableProc;

// копирование на ЖД

if ((HANDLE) _beginthread (FlowWrite, 4096, WriteInfo) == INVALID_HANDLE_VALUE)

AddLog ("Поток записи на диск запустить не удалось");

}

}

else

{

sprintf(log, "Вымещается таблица страниц процесса %d", Process->Badest);

AddLog(log);

Adress = Proc->tableVirt;

// ищем копию таблицы в файле подкачки

SwapPage = RAM->SearchSwapPage(Process->Badest, 253, Proc->countPage);

}

 

if (SwapPage >= 0)

{

sprintf (log, "Вымещаемая страница имеет копию в файле подкачки, в секторе %d.\r\n", SwapPage);

AddLog (log);

if (MovingPage >= 0)

{

// сбрасываем признаки страницы

PartTable[MovingPage].Sign = 0;

// указываем адрес страницы в файле подкачки

PartTable[MovingPage].NumPhysPage = SwapPage;

// обновляем запись о странице процесса

WriteMemory(Proc->tableVirt * SIZE_PAGE, (BYTE*)PartTable, sizeof(VirtPages) * Proc->countPage);

}

else

{

// сбрасываем признак присутствия таблицы страниц в ОП

Proc->sign = 0;

// указываем адрес таблицы в файле подкачки

Proc->tableVirt = SwapPage;

}

}

else

{

AddLog ("Ошибка! Вымещаемая страница процесса не имеет копии на ЖД\r\nSwaping прерван.\r\n");

delete(Proc);

return -1;

}

 

sprintf (log, "Копируем из файла подкачки, из сектора %d, в страницу %d ОП.\r\n", nSector, Adress);

AddLog (log);

// копируем из файла подкачки в страницу i

ReadInfo->AdrMem = Adress * SIZE_PAGE;

if ((HANDLE) _beginthread (FlowRead, 4096, ReadInfo) == INVALID_HANDLE_VALUE)

AddLog ("Поток чтения с диска запустить не удалось");

 

// обновление таблицы физических страниц

PhysPages *newPage = new PhysPages();

newPage->NumProc = nProcess;

newPage->NumVirtPage = nPage;

newPage->NumPart = nPart;

WriteMemory (RAM->TablePage + sizeof(PhysPages)*Adress, (BYTE*)newPage, sizeof(PhysPages));

delete(newPage);

 

delete(Proc);

delete(MovingProcess);

delete(Table);

 

return Adress;

}

 

// структура входных данных для потока выделения адресного пространства процессу

struct AdressSpace

{

int nProcess;

int BlockCount;

int BlockLength[10];

};

 

// Поток выделения адресного пространства процессу

void FlowMakeAddressSpace (int nProcess, int *nPage, int nPart)

{

char log[256];

 

// создаем дескриптор процесса

dCript *Proc = new dCript();

AddLog("Считываем созданый дескриптор\r\n");

ReadMemory(Process->TableProc + sizeof(dCript) * nProcess, (BYTE*)Proc, sizeof(dCript));

 

// считаем общее количество страниц

int CountPage = 0;

BYTE TablePart[10];

for (int i=0; i < nPart; i++)

{

TablePart[i] = (BYTE)CountPage;

CountPage += nPage[i];

}

 

WriteMemoryEx(RAM->TableParts + nProcess*10, TablePart, nPart);

// указываем сколько у него страниц

Proc->countPage = CountPage;

 

AddLog("Создание таблицы страниц процесса\r\n");

Proc->status = Wait;

// выделить процессу таблицу в файле подгрузки

int NumPageWithVirtTable = RAM->MakeTablePage (nProcess, nPart, nPage, 0);

// если таблица разместилась

if (NumPageWithVirtTable >= 0)

{

// номер страницы с виртуальной таблицей

Proc->tableVirt = NumPageWithVirtTable;

// признак отсутствия таблицы в оперативной памяти

Proc->sign = 0;

}

/*

иначе, невозвожно создать процесс, недостаточно памяти,

необходимо откатить изменения

*/

else

{

AddLog("Не удалось создать процесс. Недостаточно свободной памяти.\r\n");

delete(Proc);

// удаление дескриптора процесса

Process->DeleteProcess(nProcess);

return;

}

// попытка разместить страницы процесса в ОП

// сначала размещаем таблицу страниц

NumPageWithVirtTable = RAM->MakeTablePage (nProcess, nPart, nPage, 1);

// если он разместилась, то пробуем разместить остальные

if (NumPageWithVirtTable >= 0)

{

Proc->tableVirt = NumPageWithVirtTable;

Proc->sign = 1;

}

// обновляем дескриптор процесса

WriteMemory(Process->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

delete(Proc);

}

/*

Cоздать адресное пространство для указанного процесса

nProcess - номер процесса для которого создается адресное пространство

bBlockCount - количество блоков адресного пространства

для страничного распределения bBlockCount всегда равен 1

для сегментного и сегментно-страничного распределения - количество сегментов

lpBlockLength - длины блоков аресного пространства

*/

DLLFUNC void osMakeAddressSpace(int nProcess, int bBlockCount, int * lpBlockLength) {

 

int nPage[10];

// считаем общее количество страниц

nPage[0] = (lpBlockLength[0] / SIZE_PAGE);

if (lpBlockLength[0] % SIZE_PAGE)

nPage[0]++;

int CountPage = 0;

CountPage += nPage[0];

 

if (CountPage < 43)

{

// запуск выделения адресного пространства

FlowMakeAddressSpace(nProcess, nPage, bBlockCount);

}

else

{

AddLog("Задан слишком большой размер адресного пространства.\r\n");

Process->DeleteProcess(nProcess);

}

}

 

// выволнить трансляцию адреса

// nProcess - номер процесса, в адресном пространстве которого выполняется преобразование

// nVirtualAdress - виртуальный адрес, по которому пытаемся произвести обращение

// nOperationType - выполняемая операция при доступе к ячейке памяти (MemoryRead или MemoryWrite)

// функция должна вернуть номер физ. ячейки или

// -1 если необходимая часть адресного пространства отсутствует в оперативной памяти

DLLFUNC int osTranslateAddress(int nProcess, int nVirtualAdress, int nOperationType) {

char log[256];

 

// читаем дескриптор процесса из оперативной памяти виртуальной машины

dCript *Proc = new dCript();

ReadMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

 

if(Proc->status != NotExist)

osMakeEmptyCommand(nProcess);

// если таблица страниц в ОП

if (Proc->sign == 1)

{

// получаем физический адрес таблицы страниц процесса

int PhysAdress = Proc->tableVirt * SIZE_PAGE;

// чтение таблицы страниц процесса

VirtPages *PartTable = new VirtPages[Proc->countPage]();

ReadMemory (PhysAdress, (BYTE*)PartTable, sizeof(VirtPages) * Proc->countPage);

 

// определям к какой странице относится смещение

int nPage = (nVirtualAdress / SIZE_PAGE);

 

// если номер страницы превышает количество страниц процесса

if (nPage >= Proc->countPage)

return -1;

 

int lea = nVirtualAdress - (nPage * SIZE_PAGE);

 

// проверяем где находится требуемая страница

if (PartTable[nPage].Sign & 0x01)

{

int Adress = PartTable[nPage].NumPhysPage * SIZE_PAGE + lea;

if (nOperationType == MemoryRead)

{

sprintf (log, "Чтение по физическому адресу %d.\r\n", Adress);

//AddLog (log);

// установить признак обращения

PartTable[nPage].SetReference(true);

}

if (nOperationType == MemoryWrite)

{

sprintf (log, "Запись по физическому адресу %d.\r\n", Adress);

//AddLog (log);

// установить признак модификации

PartTable[nPage].SetUpdating(true);

}

 

// обновляем таблицу страниц процесса

WriteMemory (PhysAdress, (BYTE*)PartTable, sizeof(VirtPages) * Proc->countPage);

 

delete(PartTable);

delete(Proc);

return Adress;

}

// необходимо переместить страницу

else

{

AddLog ("Страница процесса находится на ЖД. Перемещение...\r\n");

// уводим процесс в ожидание

Proc->status = Wait;

WriteMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

 

VirtPages *newPage = new VirtPages();

newPage->NumPhysPage = Swaping(nProcess, nPage, PartTable[nPage].NumPart, PartTable[nPage].NumPhysPage);

newPage->NumPart = PartTable[nPage].NumPart;

newPage->SetPresence(true);

//обновляем запись о странице процесса

WriteMemory (PhysAdress + sizeof(VirtPages)*nPage, (BYTE*)newPage, sizeof(VirtPages));

delete(newPage);

}

delete (PartTable);

delete(Proc);

return -1;

}

else

{

AddLog ("Таблица страниц процесса находится на ЖД. Перемещение...\r\n");

// уводим процесс в ожидание

Proc->status = Wait;

WriteMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

 

Proc->tableVirt = Swaping(nProcess, 253, Proc->countPage, Proc->tableVirt);

Proc->sign = 1;

// обновляем дескриптор

WriteMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

return -1;

}

delete(Proc);

return -1;

}

 

// выволнить трансляцию адреса

// nProcess - номер процесса, в адресном пространстве которого выполняется преобразование

// nSegment - номер сегмента, к которому пытаемся произвести обращение

// nOffset - смещение в сегменте

// nOperationType - выполняемая операция при доступе к ячейке памяти (MemoryRead или MemoryWrite)

// функция должна вернуть номер физ. ячейки или

// -1 если необходимая часть адресного пространства отсутствует в оперативной памяти

//DLLFUNC int osTranslateAddress2(int nProcess, int nSegment, int nOffset, int nOperationType) {}

 

 

//-------------------------------------------------------------

// методы для подсистемы ввода-вывода

//-------------------------------------------------------------

 

// запись данных из оперативной памяти в указанный файл

// nProcess - номер процесса (0-99), вызвавший метод (255 - система)

// fileName - имя файла (не более 20 символов)

// virtMemBuffer - адрес буфера в адресном пространстве процесса

// если вызывается от имени системы - virtMemBuffer указывает на физ. память

// count - длина буфера на запись

// offset - позиция в файле, с которой необходимо осуществлять запись

// возращает 1 - если успех

// -1 - если ошибка

DLLFUNC int osWriteFile(int nProcess, char * fileName, int virtMemBuffer, int count, int offset) {

char log[256];

sprintf(log, "Запись файла %s из адресного пространства процесса %d по адресу %d\r\n", fileName, nProcess, virtMemBuffer);

AddLog(log);

sprintf(log, "байт для записи - %d, смещение в файле - %d\r\n", count, offset);

AddLog(log);

 

if (count < 1)

return -1;

 

// читаем дескриптор процесса из оперативной памяти виртуальной машины

dCript *Proc = new dCript();

ReadMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

// уводим процесс в ожидание

Proc->status = Wait;

WriteMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

if (Proc->sign != 1)

{

osTranslateAddress(nProcess, virtMemBuffer, MemoryRead);

return -1;

}

STdisk *ReadInfo = new STdisk;

 

// Чтение таблицы страниц процесса

VirtPages *Virt = new VirtPages[Proc->countPage]();

ReadMemory (Proc->tableVirt * SIZE_PAGE, (BYTE*)Virt, sizeof(VirtPages) * Proc->countPage);

int nPage = virtMemBuffer / SIZE_PAGE;

int sub = virtMemBuffer % SIZE_PAGE;

ReadInfo->NumPart = Virt[nPage].NumPart;

 

BYTE *TableParts = new BYTE[10];

ReadMemory (RAM->TableParts + nProcess*10, TableParts, 10);

nPage = nPage - TableParts[Virt[nPage].NumPart];

ReadInfo->firstByte = nPage * SIZE_PAGE + sub;

 

memcpy(ReadInfo->FileName, fileName, 20);

// смещение в файле

ReadInfo->offset = offset;

 

// количество байт на запись

ReadInfo->count = count;

// страница для обмена между динамически выделенными буфферами и Диском

ReadInfo->DataPage = RAM->DataPage;

// таблица процессов, для того что бы увести и вывести процесс в/из ожидания

ReadInfo->TableProc = RAM->TableProc;

ReadInfo->TableIN = RAM->TableIN;

// процесс который будет уводится в ожидание и выводится из него

ReadInfo->nProc = nProcess;

 

// копирование на ЖД

if ((HANDLE) _beginthread (TreadWriteFile, 4096*2, ReadInfo) == INVALID_HANDLE_VALUE)

AddLog ("Поток чтения с диска запустить не удалось");

 

return 1;

}

 

// nSegment - номер сегмента в виртуальном адресном пространстве процесса

// nPartOffset - смещение в сегменте

//DLLFUNC int osWriteFile2(int nProcess, char * fileName, int nSegment, int nPartOffset, int count, int offset) {}

 

int WriteExternFile (char * fileName, BYTE * lpBuffer, int count, int nProcess)

{

if (count == 0)

{

AddLog ("Ошибка: Попытка создания пустого файла!\r\n");

return -1;

}

 

// вычисляем количество кластеров которые будет занимать файл

int Count = (count / SIZE_CLUSTER);

if (count % SIZE_CLUSTER != 0)

Count++;

 

// если достаточно свободного места в оперативной памяти

if (HD->CheckFreeSpace() >= Count)

{

// проверяем на присутствие файла с таким именем

int NumFile = HD->FindFile(fileName);

 

// если есть файл, удаляем его

if (NumFile >= 0)

{

sFile *File = new sFile();

ReadMemory (HD->TableFile + sizeof(sFile)*NumFile, (BYTE*)File, sizeof(sFile));

 

HD->DeleteSpace(File->firstCluster);

HD->DeleteFile(NumFile);

 

delete(File);

}

 

// резервируем адресное пространство процессу

WORD First = HD->ReservSpace(Count);

 

// добавляем запись о файле в таблицу файлов

int Num = HD->CreateFile(fileName, count, First);

 

if ( Num >= 0)

{

AddLog ("Файл создан. Начат процесс записи содержимого файла.\r\n");

// записываем данные в пространства файла

HD->WriteFile(Num, lpBuffer, nProcess, Process->TableProc);

}

else

{

AddLog ("Не удалось записать файл. Достигнуто максимальное количество фалов.\r\n");

// если создано максимальное количество файлов удалить выделеное файлу место

HD->DeleteSpace(First);

return -1;

}

}

else

{

AddLog ("Не удалось записать файл. Недостаточно свободного места.\r\n");

return -1;

}

 

return 1;

}

 

// запись данных в файл из указанного внешнего буфера

// fileName - имя файла (не более 20 символов)

// lpBuffer - адрес буфера с данными

// count - длина буфера на запись

// возращает 1 - если успех

// -1 - если ошибка

DLLFUNC int osWriteExternFile(char * fileName, BYTE * lpBuffer, int count) {

 

int res = WriteExternFile (fileName, lpBuffer, count, 255);

return res;

}

 

// чтение из файла данных в оперативную память

// nProcess - номер процесса (0-99), вызвавший метод (255 - система)

// fileName - имя файла (не более 20 символов)

// virtMemBuffer - адрес буфера в адресном пространстве процесса

// если вызывается от имени системы - virtMemBuffer указывает на физ. память

// count - длина буфера на чтение

// offset - позиция в файле, с которой необходимо осуществлять чтение

// возращает количество прочитанных символов

// -1 - если ошибка

DLLFUNC int osReadFile(int nProcess, char * fileName, int virtMemBuffer, int count, int offset) {

char log[256];

 

sprintf(log, "Чтение файла %s в адресное пространство процесса %d по адресу %d\r\n", fileName, nProcess, virtMemBuffer);

AddLog(log);

sprintf(log, "байт для чтения - %d, смещение в файле - %d\r\n", count, offset);

AddLog(log);

 

if (count < 1)

return -1;

 

dCript *Proc = new dCript();

ReadMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

Proc->status = Wait;

WriteMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

if (Proc->sign != 1)

{

osTranslateAddress(nProcess, virtMemBuffer, MemoryRead);

return -1;

}

 

sFile *File = new sFile();

// ищем файл с таким именем

int Num = HD->FindFile(fileName);

// если находим такой файл

if (Num >= 0)

{

// читаем запись о нем

ReadMemory (RAM->TableFile + sizeof(sFile)*Num, (BYTE*)File, sizeof(sFile));

if (offset + count > File->fileSize)

{

AddLog("Размер файла меньше требуемого!\r\n");

ReadMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

Proc->status = Ready;

WriteMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

return -1;

}

 

// Получаем номер сектора из которого будем читать

int nSector = offset / SIZE_CLUSTER;

nSector = HD->GetSector(File->firstCluster, nSector);

int SizeBuffer = count / SIZE_CLUSTER;

if (count % SIZE_CLUSTER != 0)

SizeBuffer++;

// вычисляем смещение в секторе

int sub = offset - (offset / SIZE_CLUSTER) * SIZE_CLUSTER;

// если смещение не кратно сектору, т.е. информацию придется начинать писать не с начала сектора

if (sub + count > SIZE_CLUSTER)

SizeBuffer++;

 

STdisk *ReadInfo = new STdisk;

 

// Чтение таблицы страниц процесса

VirtPages *Virt = new VirtPages[Proc->countPage]();

ReadMemory (Proc->tableVirt * SIZE_PAGE, (BYTE*)Virt, sizeof(VirtPages) * Proc->countPage);

int nPage = virtMemBuffer / SIZE_PAGE;

int subPage = virtMemBuffer % SIZE_PAGE;

ReadInfo->NumPart = Virt[nPage].NumPart;

 

BYTE *TableParts = new BYTE[10];

ReadMemory (RAM->TableParts + nProcess*10, TableParts, 10);

nPage = nPage - TableParts[Virt[nPage].NumPart];

ReadInfo->firstByte = nPage * SIZE_PAGE + subPage;

 

// сектор с которого начнем запись

ReadInfo->Sector = nSector;

// смещение в секторе

ReadInfo->offset = sub;

// количество байт на запись

ReadInfo->count = count;

// страница для обмена между динамически выделенными буфферами и Диском

ReadInfo->DataPage = RAM->DataPage;

// таблица процессов, для того что бы увести и вывести процесс в/из ожидания

ReadInfo->TableProc = RAM->TableProc;

ReadInfo->TableIN = RAM->TableIN;

// процесс который будет уводится в ожидание и выводится из него

ReadInfo->nProc = nProcess;

// количество байт для считывания, записи в файл

ReadInfo->Size = SizeBuffer * SIZE_CLUSTER;

 

// копирование на ЖД

if ((HANDLE) _beginthread (TreadReadFile, 4096*2, ReadInfo) == INVALID_HANDLE_VALUE)

AddLog ("Поток чтения с диска запустить не удалось");

return 1;

}

else

{

AddLog("Файл не существует!\r\n");

ReadMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

Proc->status = Ready;

WriteMemory (RAM->TableProc + sizeof(dCript)*nProcess, (BYTE*)Proc, sizeof(dCript));

return -1;

}

return -1;

}

 

// nSegment - номер сегмента в виртуальном адресном пространстве процесса

// nPartOffset - смещение в сегменте

//DLLFUNC int osReadFile2(int nProcess, char * fileName, int nSegment, int nPartOffset, int count, int offset) {}

 

// чтение из файла данных в указанный внешнний буфер

// fileName - имя файла (не более 20 символов)

// lpBuffer - адрес буфера с данными

// count - длина буфера на для данных

// возращает количество прочитанных символов

// -1 - если ошибка

 








Не нашли, что искали? Воспользуйтесь поиском по сайту:



©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.