1.题目要求
编写一个程序,包括两个线程,一个线程用于模拟内存分配活动,另一个用于跟踪第一个线程的内存行为,要求两个线程之间通过信号量实现同步,模拟内存活动的线程可以从一个文件中读出要进行的内存操作。每个内存操作包含如下内容:
时间:每个操作等待时间;
块数:分配内存的粒度;
操作:包括保留一个区域、提交一个区域、释放一个区域、回收一个区域、加锁与解锁一个区域。可将它们的编号放置于一个文件中。
保留是指保留进程的虚地址空间,而不分配物理地址空间;
提交是指在内存中分配物理地址空间;
回收是指释放物理地址空间,而保留进程的虚地址空间;
释放是指将进程的物理地址与虚拟地址空间全部释放;
大小:块的大小;
访问权限:共五种PAGE_READONLY, PAGE_READWRIYE, PAGE_EXEXUTE, PAGE_EXEXUTE _READ, PAGE_EXEXUTE _READWRIYE.
2.测试样例随机生成
定义操作和权限的方式采用了两层循环,外层循环控制对内存的操作,内层循环控制对内存的权限。随机生成。
#include <iostream>
#include <stdlib.h>
#include "fstream"
using namespace std;
struct operation
{
int time; //起始时间
int block;//内存页数
int oper; //操作
int protection;//权限
};
int main()
{
FILE *file ;
file=fopen("file","wb");//opfile为二进制,用于确定内存操作
operation op;
for(int j=0; j<6; j++) //0-保留;1-提交;2-锁;3-解锁;4-回收;5-释放
for(int i = 0; i<5; i++)
/*0-PAGE_READONL
1-PAGE_WRITE
2-PAGE_EXECUTE
3-PAGE_EXECUTE_READ
4-PAGE_EXECUTE_READWRITE*/
{
op.time=rand()%1000; //随机生成等待时间
op.block=rand()%5+1;//随机生成块
op.oper=j;
op.protection=i;
fwrite(&op,sizeof(operation),1,file);//将生成的结果写入文件
}
return 0;
}
3.详细设计
主函数模块
1.创建两个线程,并将返回的句柄存入数组中。
handle[0]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Tracker,NULL,0,&dwThread);
handle[1]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Allocator,NULL,0,&dwThread);
2.创建两个信号量(allo,trac)分别用来通知跟踪线程和记录线程。
allo=CreateSemaphore(NULL,0,1,"allo");
trac=CreateSemaphore(NULL,0,1,"trac");
3.用函数WaitForMultipleObjects等待两个线程的结束。
跟踪线程的内存行为,并输出必要信息子模块
1.打开文件out.txt准备输出。
2.等待线程Allocator的一次内存操作完毕(即等待信号量trac的释放)。WaitForSingleObject(trac,INFINITE);
3.用函数SYSTEM_INFO info ; GetSystemInfo(&info);获得系统信息。
4.用MEMORYSTATUS status ;GlobalMemoryStatus(&status);得到内存信息。用函数VirtualQuery得到虚拟内存的基本信息。
5.释放信号量,通知Allocator线程可以进行下一步的分配活动。
6.如果硬件记录了所有的内存分配情况则线程退出,否则转到第2步。
模拟内存分配活动的线程子模块
1.打开文件(file)准备读入文件内容。
2.等待Tracker输出的结束(等待信号量allo释放)。
3.读文件(file)。
4.根据文件内容(protection)确定对内存的操作的权限。
5.根据文件内容(oper)确定对内存的具体操作。
6.释放信号量(trac)通知Tracker线程可以进行一次输出 。
7.如果文件中的所有分配信息已经完成,线程退出,否则转到第2步。
4.代码
#include <iostream>
#include <stdlib.h>
#include <windows.h>
#include "fstream"
using namespace std;
struct operation
{
int time;//起始时间
int block;//内存页数
int oper;//操作
int protection;//权限
};
struct trace
{
LPVOID start;//起始地址
long size;//分配的大小
};
HANDLE allo,trac;
DWORD Tracker(LPDWORD lpdwparm)//跟踪线程的内存行为,并输出必要信息
{
ofstream outfile;
outfile.open("out.txt");
for(int i=0; i<=30; i++)
{
WaitForSingleObject(trac,INFINITE);//等待allocator一次内存分配活动结束
//打印内存状况和系统状况
outfile<<i<<endl;
SYSTEM_INFO info;//系统信息
GetSystemInfo(&info);
outfile<<"页面文件大小"<<'\t'<<info.dwPageSize<<endl;
outfile<<"进程的最小内存地址"<<'\t'<<info.lpMinimumApplicationAddress<<endl;
outfile<<"进程的最大内存地址"<<'\t'<<info.lpMaximumApplicationAddress<<endl;
outfile<<"当前活动的CPU"<<'\t'<<info.dwActiveProcessorMask<<endl;
outfile<<"CPU的个数"<<'\t'<<info.dwNumberOfProcessors<<endl;
outfile<<"分配粒度"<<'\t'<<info.dwAllocationGranularity<<endl;
outfile<<"当前处理器结构图"<<'\t'<<info.dwProcessorType<<endl;
outfile<<"_______________________________________________________"<<endl;
MEMORYSTATUS status;//内存状态
GlobalMemoryStatus(&status);
outfile<<"MEMORYSTATUS结构的大小"<<'\t'<<status.dwLength<<endl; // sizeof(MEMORYSTATUS)
outfile<<"系统内存的使用率"<<'\t'<<status.dwMemoryLoad<<endl; // percent of memory in use
outfile<<"总的物理内存大小"<<'\t'<<status.dwTotalPhys<<endl; // bytes of physical memory
outfile<<"可用的物理内存大小"<<'\t'<<status.dwAvailPhys<<endl; // free physical memory bytes
outfile<<"显示可以存在页面文件中的字节数"<<'\t'<<status.dwTotalPageFile<<endl; // bytes of paging file
outfile<<"可用的页面文件大小"<<'\t'<<status.dwAvailPageFile<<endl; // free bytes of paging file
outfile<<"用户模式的全部可用虚拟地址空间"<<'\t'<<status.dwTotalVirtual<<endl; // user bytes of address space
outfile<<"实际自由可用的虚拟地址空间"<<'\t'<<status.dwAvailVirtual<<endl; // free user bytes
outfile<<"__________________________________________________"<<endl;
//释放信号量通知allocator 可以执行下一次内存分配活动
ReleaseSemaphore(allo,1,NULL);
}
return 0;
}
void Allocator()//模拟内存分配活动的线程
{
trace traceArray[5];
int index=0;
FILE* file;
file=fopen("file","rb");//读入文件
operation op;
SYSTEM_INFO info;
DWORD temp;
GetSystemInfo(&info);
for(int i=0; i<30; i++)
{
WaitForSingleObject(allo,INFINITE);//等待tracker打印结束的信号量
cout<<i<<endl;
fread(&op,sizeof(operation),1,file);
Sleep(op.time);//执行时间
GetSystemInfo(&info);
switch(op.protection)
{
case 0:
{
index=0;
temp=PAGE_READONLY;
break;
}
case 1:
temp=PAGE_READWRITE;
break;
case 2:
temp=PAGE_EXECUTE;
break;
case 3:
temp=PAGE_EXECUTE_READ;
break;
case 4:
temp=PAGE_EXECUTE_READWRITE;
break;
default:
temp=PAGE_READONLY;
}
switch(op.oper)
{
case 0:
{
cout<<"reserve now"<<endl;
traceArray[index].start=VirtualAlloc(NULL,op.block *info.dwPageSize,MEM_RESERVE,PAGE_NOACCESS);
traceArray[index++].size=op.block *info.dwPageSize;
cout<<"strating address:"<<traceArray[index-1].start<<'\t'<<"size:"<<traceArray[index-1].size<<endl;
break;
}
case 1:
{
cout<<"commit now"<<endl;
traceArray[index].start=VirtualAlloc(traceArray[index].start,traceArray[index].size,MEM_COMMIT,temp);
index++;
cout<<"strating address:"<<traceArray[index].start<<'\t'<<"size:"<<traceArray[index].size<<endl;
break;
}
case 2:
{
cout<<"lock now"<<endl;
cout<<"strating address:"<<traceArray[index].start<<'\t'<<"size:"<<traceArray[index].size<<endl;
if(!VirtualLock(traceArray[index].start,traceArray[index++].size))
cout<<GetLastError()<<endl;
break;
}
case 3:
{
cout<<"unlock now"<<endl;
cout<<"strating address:"<<traceArray[index].start<<'\t'<<"size:"<<traceArray[index].size<<endl;
if(!VirtualUnlock(traceArray[index].start,traceArray[index++].size))
cout<<GetLastError()<<endl;
break;
}
case 4:
{
cout<<"decommit now"<<endl;
cout<<"strating address:"<<traceArray[index].start<<'\t'<<"size:"<<traceArray[index].size<<endl;
if(!VirtualFree(traceArray[index].start,traceArray[index++].size,MEM_DECOMMIT))
cout<<GetLastError()<<endl;
break;
}
case 5:
{
cout<<"release now"<<endl;
cout<<"strating address:"<<traceArray[index].start<<'\t'<<"size:"<<traceArray[index].size<<endl;
if(!VirtualFree(traceArray[index++].start,0,MEM_RELEASE))
cout<<GetLastError()<<endl;
break;
}
default:
cout<<"error"<<endl;
}
ReleaseSemaphore(trac,1,NULL);
}
}
int main()
{
DWORD dwThread;
HANDLE handle[2];
handle[0]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Tracker,NULL,0,&dwThread);
handle[1]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Allocator,NULL,0,&dwThread);
allo=CreateSemaphore(NULL,0,1,"allo");
trac=CreateSemaphore(NULL,1,1,"trac");
WaitForMultipleObjects(2,handle,TRUE,INFINITE);
return 0;
}