Программная реализация системы
Библиотека функций 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 - 2025 stydopedia.ru Все материалы защищены законодательством РФ.
|