программа Менеджер страничной памяти - Пытаюсь разобраться
Код программы
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#define MSZ 10240
#define PSZ 1024
#define PCNT 18
#define RPCNT 8
char memory[MSZ]; // массив с памятью
struct sPages
{
char id[PCNT]; // просто id странички
char rwCnt[PCNT]; // количество обращений к странице, если -1, то это не занятая страница
char pos[PCNT]; // позиция в памяти
};
struct sAllocated
{
char data[PCNT][PCNT]; // табличка для хранения списка страниц для пользователя (по id набора)
};
struct sPage
{
char data[PSZ]; // просто данные
};
sPages* info; // указатель на список
sPage* tData; // временная страница (для обмена с файлами местами)
sAllocated* alc; // указатель но таблицу с наборами страниц
void fr(char* data,int num) // чтение файла странички по её id
{
char name[3] = "c/"; // все странички в папке "c"
name[2] = (char)(num + 97); // с именем по номеру буквы в алфавите
FILE * pFile;
pFile = fopen(name,"r");
if(pFile==NULL)return;
fgets(data,PSZ,pFile);
fclose(pFile);
}
void fw(char* data,int num) // запись файла странички по её id
{
char name[3] = "c/";
name[2] = (char)(num + 97);
FILE * pFile;
pFile = fopen(name,"a");
if(pFile==NULL)return;
fputs(data,pFile);
fclose(pFile);
}
int getPageFromSmallRwCnt() // получить страничку в оперативной памяти, у которой минимальный счётчик обращений
{
int id,rwCnt,pos;
id = info->id[0];
rwCnt = 255;
pos = 0;
int i;
i = PCNT;
while(i--)
{
if(info->rwCnt < rwCnt && info->pos < RPCNT/* && info->rwCnt != -1*/)
{
rwCnt = info->rwCnt;
id = info->id;
pos = i;
}
}
return pos;
}
sPage* getPageForReadOrWrite(char id) // получить указатель на страничку для чтения или записи туда (функция сама должна перемещать страницу в оперативную память по надобности и прибавлять счётчик обращений)
{
sPage* tmp;
char idtmp,rwtmp;
int i;
int cpage = -1;
i = PCNT;
while(i--) // ищем по id
{
if(info->id == id)
{
cpage = i;
i = 0;
}
}
if(info->pos[cpage] < RPCNT) // если страничка и так в оперативной памяти, то всё хорошо
{
info->rwCnt[cpage] ++; // прибавим счётчик
return (sPage*)(&memory[info->pos[cpage] * PSZ]); // просто вернём её адрес
}else // если нет... =(
{
int rampage = getPageFromSmallRwCnt();
//printf("%d\n\n",rampage);///////////////////////////////////////////////////////////////////////////////////////////////////////////////
fr((char*)tData,info->pos[cpage]); // читаем страничку в буфер
tmp = (sPage*)(&memory[info->pos[rampage] * PSZ]);
fw((char*)tmp,info->pos[cpage]); // пишем образ странички из оперативной памяти на диск
for(int z = 0;z < PSZ;z ++)
tmp->data[z] = tData->data[z]; // копируем буфер в оперативную память
// далее меняем местами параметры странички
idtmp = info->id[rampage];
rwtmp = info->rwCnt[rampage];
info->id[rampage] = info->id[cpage];
info->rwCnt[rampage] = info->rwCnt[cpage];
info->id[cpage] = idtmp;
info->rwCnt[cpage] = rwtmp;
info->rwCnt[rampage] ++; // прибавим счётчик
return (sPage*)(&memory[info->pos[rampage] * PSZ]); // вернём адрес
}
} // лучше ничего не менять в этой функции. главное работает
char getPagePosById(char id)
{
int i = 0;
for(i = 0;i < PCNT;i ++)
{
if(info->id == id)return info->pos;
}
}
void dump(int a = 0) // отладочная информация
{
int i = 0;
int j = 0;
if(a)
{
printf("ID\tPOS\tRWCNT\n\n");
for(i = 0;i < PCNT;i ++)
{
printf("%d\t%d\t%d\n",info->id,info->pos,info->rwCnt);
}
printf("\n\n");
for(i = 0;i < PCNT;i ++)
{
printf("\n");
for(j = 0;j < PCNT;j ++)
printf("%d ",alc->data[j]);
}
}
printf("BLOCK_ID\tPAGES\n");
for(i = 0;i < PCNT;i ++)
{
if(alc->data[0] == -1)continue;
if(i < 10)
printf("%d.........\t",i);
else
printf("%d........\t",i);
for(j = 0;j < PCNT;j ++)
{
if(alc->data[j] != -1)printf("%d ",getPagePosById(alc->data[j]));
}
printf("\n");
}
}
int alloc(int size) // занять кусок памяти размером size
{
int i = 0;
int n = 0;
int m = 0;
int tblid = 0;
while(alc->data[tblid][0] != -1)
{
tblid ++;
}
if(tblid > PCNT)return -1;
while(size > 0)
{
size -= PSZ;
i = PCNT;
m = -1;
while(i--)
{
if(info->rwCnt == -1)
{
m = info->id;
info->rwCnt = 0;
i = 0;
}
}
if(m == -1)return -1;
alc->data[tblid][n] = m;
n ++;
}
return tblid;
}
void setById(int id,int rwCnt) // установщик rwCnt по id
{
int i =0;
while(info->id != id) // ищем
{
i ++;
}
info->rwCnt = rwCnt; // устанавливаем
}
void free(int id) // высвобождение по id
{
for(int i = 0;i < PCNT;i ++)
{
if(alc->data[id] != -1)setById(alc->data[id],-1);
alc->data[id] = -1;
}
}
void write(int id,int size,int offset,char* data) // пишем
{
sPage* tmp;
int start = offset / PSZ;
int start_offset = offset - start * PSZ;
int cur = 0;
int sp = start_offset; // позиция для записи
int pp = start; // номер страницы
if(alc->data[id][pp] != -1)
tmp = getPageForReadOrWrite(alc->data[id][pp]);
else
return;
while(size--)
{
if(sp >= PSZ)
{
sp = 0;
pp ++;
if(alc->data[id][pp] != -1)
tmp = getPageForReadOrWrite(alc->data[id][pp]); // получаем адрес страницы
else
return;
}
if(pp >= PCNT)return;
//
tmp->data[sp] = data[cur];
cur++;
//
sp ++;
}
}
void read(int id,int size,int offset,char* data) // чтение (абсолютно аналогично записи)
{
sPage* tmp;
int start = offset / PSZ;
int start_offset = offset - start * PSZ;
int cur = 0;
int sp = start_offset;
int pp = start;
if(alc->data[id][pp] != -1)
tmp = getPageForReadOrWrite(alc->data[id][pp]);
else
return;
while(size--)
{
if(sp >= PSZ)
{
sp = 0;
pp ++;
if(alc->data[id][pp] != -1)
tmp = getPageForReadOrWrite(alc->data[id][pp]);
else
return;
}
if(pp >= PCNT)return;
//
data[cur] = tmp->data[sp]; // только в этой строке отличие
cur++;
//
sp ++;
}
}
void init() // инициализация
{
int i;
for(i = 0;i < MSZ;i ++)memory = 0x00; // память ноликами
info = (sPages*)(&memory[MSZ - PSZ]); // указатели
tData = (sPage*)(&memory[MSZ - PSZ * 2]); // ...
alc = (sAllocated*)(&memory[MSZ - PSZ / 2]); // ...
for(i = 0;i < PCNT;i ++)
{
info->id = i;
info->rwCnt = -1;
info->pos = i;
if(i > RPCNT)fw(memory,i); // файлики
for(int j = 0;j < PCNT;j ++)
alc->data[j] = -1;
}
}
int main()
{
init();
//dump(1);
char tmp0[5000] = "teststring0teststring0teststring0teststring0teststring0teststring0teststring0";
char tmp1[5000] = "samplestring1samplestring1samplestring1samplestring1samplestring1samplestring1";
char tmp2[5000] = "helloworld2helloworld2helloworld2helloworld2helloworld2helloworld2";
char tmp3[5000] = "smileystring3smileystring3smileystring3smileystring3smileystring3smileystring3smileystring3";
int id0,id1,id2,id3,id4,id5;
//dump();
id0 = alloc(2048);
id1 = alloc(2048);
id2 = alloc(1024);
id3 = alloc(12288);
id4 = alloc(1024);
dump();
write(id1,10,1400,tmp0);
dump();
write(id1,10,400,tmp1);
dump();
write(id3,100,7*1024,tmp2);
dump();
write(id0,200,100,tmp3);
dump();s
//read(id1,10,400,tmp0);
//printf("\n\n\n%s\n\n\n",tmp0);
getch();
return 0;
}