操作系统实验4
题目1:编写页面内存的LRU替换算法
在实验3基础上考虑,如果当前分配的内存或保存页面的数据项已经被用完,这时再有新的网页请求,需要对已在内存中的网页数据进行替换,本实验内容需要使用LRU算法来对内存中的网页数据进行替换
题目2:编写页面内存的LFU替换算法
实现LFU(最少访问频率的页面替换)算法来管理内存页面
实验报告要求:
- 实验报告封面如下页所示。
- 按照题目要求,完成相关实验题目。
2.1报告中要包含完成此题目所查阅的一些关键技术材料。例如内存结构的设计、分配管理、回收方法等内容。
2.2 报告中有实现的关键技术点源代码,源代码书写要有一定的规范,源代码中有相关的注释
2.3 作为扩展,在界面上能够定时给出当前内存的占用情况。因此根据上面的题目,可以适当地增加对其它方面的信息监控。
操作系统实验报告四
姓名:许恺
学号:2014011329
日期:12月7日
一.构思想法
题目1:编写页面内存的LRU替换算法
因为web4和3太像了,所以并没有什么难度,我只需要将替换的页面改一下就可以了,所以我加了一个属性,就是这个页面是第几个被申请的,这样既可以记录网页申请的流量,也可以将在内存中的数字最小的那个替换掉,也就是LRU算法所讲的最久未被用的那个,然后加上时间函数计算出每次用的时间进行分析报告就可以了。
题目2:编写页面内存的LFU替换算法
其实我想说我web3用的就是LFU替换算法,老师可以看我的web3报告,或者这份报告也可以,这份报告会给出对于一串申请序列,两种方法比较的时间分析。
二.源代码以及结果贴图和分析
题目1:编写页面内存的LRU替换算法
关键代码(有修改):
Webserver4.cpp: // webserver4.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <Winsock2.h> #include <windows.h> #include <string> #include <fstream> #include "PageMemo.h" PageMemo Mem; //初始化内存中的网页 SOCKET socketconn; static string dir = "D:\xukai\学习\操作系统实验\网页"; //文件路径 int num = 1; //请求网页次数 #include "Thread.h" #include "CMyTask.h" #pragma comment(lib, "ws2_32.lib") using namespace std; void main(int argc, _TCHAR* argv[]) { CMyTask taskObj; CThreadPool threadPool(10); double alltime=0;//运行总时间 LARGE_INTEGER large_interger; double dff; __int64 c1, c2; QueryPerformanceFrequency(&large_interger); dff = large_interger.QuadPart; QueryPerformanceCounter(&large_interger); //初始化WinSock库 WORD wVersionRequested; WSADATA wsaData; cout << "初始化库成功" << endl; wVersionRequested = MAKEWORD(2, 2); int wsaret = WSAStartup(wVersionRequested, &wsaData); if (wsaret) return; //创建SOCKET SOCKET socketSrv; socketSrv = socket(AF_INET, SOCK_STREAM, 0); if (socketSrv == INVALID_SOCKET) return; cout << "创建socket成功" << endl; SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(80); //绑定套接字 if (bind(socketSrv, (struct sockaddr*)&addrSrv, sizeof(SOCKADDR))) { //关闭连接 shutdown(socketSrv, 1); closesocket(socketSrv); WSACleanup(); return; } cout << "绑定套接字成功!" << endl; //等待客户端连接 SOCKADDR_IN addrCli; int len = sizeof(SOCKADDR); //监听端口 if (listen(socketSrv, 5) == SOCKET_ERROR) { printf("监听失败! "); } while (true) { socketconn = accept(socketSrv, (SOCKADDR*)&addrCli, &len); //接受连接 if (socketconn == SOCKET_ERROR) { printf("接受连接失败! "); return; } cout << "连接成功" << endl; //用QueryPerformanceCounter()来计时 微秒 c1 = large_interger.QuadPart; taskObj.SetData((void*)0); //将任务内容设到对象里 threadPool.AddTask(&taskObj); //将任务对象添加到线程池的任务队列 CThreadPool::Threadfunction(); QueryPerformanceCounter(&large_interger); c2 = large_interger.QuadPart; alltime = alltime + (c2 - c1) / dff; printf("本次用时%lf微秒 ", (c2 - c1) / dff); cout << "到现在为止共用时间:" << alltime << "微秒。" << endl; num++; } shutdown(socketSrv, 1); closesocket(socketSrv); //关闭连接 WSACleanup(); } PageMemo.h: #pragma once #include <string> #include <fstream> #include <iostream> using namespace std; /* 用来放网页的内存结构类 */ class PageMemo { public: /* ***内存结构构造函数,建立10个页面信息,从磁盘写入内存10个网页信息*** */ PageMemo() { //ifstream fp[10]; //用10个文件读的对象 //int i; //string which = ""; //for (i = 0; i < 10; i++) //{ // which = to_string(i); // file[i] = "D:\xukai\学习\操作系统实验\网页\" + which + ".html "; // //cout << file[i] << endl; // fp[i].open(file[i], std::ios::binary); // //打开文件失败 // if (!fp[i].is_open()) // { // cout << "请求文件" << which + ".html" << "不存在" << endl; // } // else//打开文件成功并读取 // { // char buffer[1024]; // while (fp[i].good() && !fp[i].eof()) // { // fp[i].getline(buffer, 1024); // //cout << buffer << endl; // //将读取的内容追加入sendBuf中 // Page[i].append(buffer); // //cout << Page[i] << endl; // buffer[0] = ' '; // } // } // fp[i].close(); //} } ~PageMemo() { } /* ****LRU算法的函数,找出前面最久未使用的页面替换 */ int LRU() { int M = lru[0], X = 0; for (int i = 1; i < 10; i++) { if (lru[i] < M) { X = i; M = lru[i]; } } return X; } /* ***求出被用过次数最少的内存中的页面,用的最普通的算法*** */ int Min() { int M = User_f[0], X = 0; for (int i = 1; i < 10; i++) { if (User_f[i] < M) { X = i; M = User_f[i]; } } return X; } /* ***在屏幕上打印当前页面的路径信息和使用次数*** */ void print() { cout << "现在要输出我当前的网页的内存信息:" << endl; for (int i = 0; i < 10; i++) { cout << " " << file[i] << " " << User_f[i]<<" "<<lru[i] << endl; } } //得到第i条路径的内容 string getfile(int i) { return file[i]; } //得到第i个页面的内容 string getPage(int i) { return Page[i]; } //得到第i个页面使用次数 int getUser_f(int i) { return User_f[i]; } //使用过一次这个网页了,使用次数+1 void plusone(int i) { User_f[i]++; } //修改file内容函数 void writefile(int i, string f) { file[i] = f; } //修改Page内容函数 void writePage(int i, string p) { Page[i] = p; } //修改User_f值的函数 void writeUser_f(int i, int n) { User_f[i] = n; } //当网页被使用,修改他的lru void writelru(int i, int n) { lru[i] = n; } private: string file[10]; //页面路径 string Page[10]; //页面信息 int User_f[10] = { 0 }; //使用次数 int lru[10] = { 0 }; //此网页第几个被使用,最小的就是最久没被用的 }; CMyTask.h: #pragma once #include "Thread.h" #include "windows.h" #include "PageMemo.h" class CMyTask : public CTask { public: CMyTask() {} inline int Run() { printf("Process startup! "); //init WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2, 2); WSAStartup(wVersionRequested, &wsaData); DWORD pid = ::GetCurrentProcessId(); sockaddr_in sa; int add_len = sizeof(sa); if (socketconn != INVALID_SOCKET) { getpeername(socketconn, (struct sockaddr *)&sa, &add_len); //while (1) //{ //连接成功后与客户端进行会话 char recvBuff[10000]; string sendBuf; string locDir; ifstream fp; //接收请求 if (recv(socketconn, recvBuff, 10000, 0) == SOCKET_ERROR) { printf("%d ", socketconn); printf("error!"); getchar(); return 0; } //读取http请求头 string recvBuffer = recvBuff; int posGet = recvBuffer.find("GET", 0); int posHttp = recvBuffer.find("HTTP", 0); //截取html文件路径 for (int pos = posGet + 4; pos < posHttp; pos++) { if (recvBuffer[pos] == '/') { locDir.push_back('\'); continue; } locDir.push_back(recvBuffer[pos]); } locDir = dir + locDir; int i; //打开http请求文件进行读取 for (i = 0; i < 10; i++) //看看内存里有没有现成的 { //cout << locDir << endl; //cout << Mem.getfile(i) << endl; if (strcmp(locDir.c_str(), Mem.getfile(i).c_str()) == 0) //匹配字符串 { cout << "在内存中找到相应的页面信息啦!!!" << endl; Mem.plusone(i); //使用次数+1 //cout << Mem.getPage(i) << endl; sendBuf = Mem.getPage(i); break; } } if (i == 10) //内存中没有,从磁盘中调取 { cout << "555555,/(ㄒoㄒ)/~~还得从磁盘取~~" << endl; fp.open(locDir.c_str(), std::ios::binary); //打开文件失败 if (!fp.is_open()) { cout << "请求文件" << locDir.c_str() << "不存在" << endl; } else//打开文件成功并读取 { char buffer[1024]; while (fp.good() && !fp.eof()) { fp.getline(buffer, 1024); //将读取的内容追加入sendBuf中 sendBuf.append(buffer); buffer[0] = '