操作系统实验报告
一、实验名称 :页面置换算法
二、实验目的:
在实验过程中应用操作系统的理论知识。
三、实验内容:
采用C/C++编程模拟实现:FIFO算法、LRU算法、LFU算法、NRU算法四个页面置换算法。并设置自动数据生成程序,比较四个算法的缺页出现概率。
四、程序代码:
/* FIFO: 简单的先进先出,用队列模拟即可 prio 表示入队时间(小值先出) LRU: 淘汰最久没有被访问的页面 prio 表示上一次入队的时间(小值先出) LFU: 淘汰最少访问次数的页面 prio 表示被访问的次数 NRU: 四类 prio表示状态类数 第0类:没有被访问,没有被修改。00 第1类:没有被访问,已被修改。 01 第2类:已被访问,没有被修改。 10 第3类:已被访问,已被修改 11 */
#include<bits/stdc++.h>
#define xcx(x) printf("ojbk %d\n",x)
using namespace std ;
const int PAGE_NUM = 20 ;
const int MEM_SIZE = 3 ;
const double NRU_LIMIT = 3 ;
bool in_mem[ PAGE_NUM+1 ] ;
struct page{
int val, prio, pos ; // val:页数 pos:占内存位置
page () {}
page ( int val , int prio , int pos ) {
this->val = val ;
this->prio = prio ;
this->pos = pos ;
}
};
bool operator < ( const page &l , const page &r ) {
if ( l.prio== r.prio ) {
return l.pos < r.pos ;
}
return l.prio > r.prio ;
}
vector< int > CreatSeq ( int n ) { // 随机生成长度为 n 的访问序列
vector< int > ret ;
for( int i=0; i<n; i++ ) {
ret.push_back( rand()%PAGE_NUM+1 ) ;
}
return ret ;
}
void Init ( vector< vector<int> > &ret , vector< bool > &is_miss , const vector< int > &seq ) {
vector< int > e( MEM_SIZE ) ;
memset( in_mem, false, sizeof(in_mem) ) ;
is_miss.clear() ; ret.clear() ;
for( int i=0; i<seq.size(); i++ ) {
is_miss.push_back( 0 ) ;
ret.push_back( e ) ;
}
}
vector< vector<int> > FIFO ( const vector< int > &seq , vector< bool > &is_miss ) {
vector< vector<int> > ret ;
Init( ret , is_miss , seq ) ;
queue< page > q ;
bool is_full = false ;
int num = 0, mem_pos[ MEM_SIZE ] = {0} ;
for( int i=0; i<seq.size(); i++ ) {
if ( in_mem[seq[i]] == false ) { // 不在mem
is_miss[i] = true ;
if ( is_full == true ) { // mem已满,淘汰
page temp = q.front() ;
q.pop() ; in_mem[ temp.val ] = false ;
q.push( page( seq[i], i+1, temp.pos ) ); in_mem[ seq[i] ] = true ;
mem_pos[temp.pos] = seq[i] ;
}
else { // mem未满,添加
q.push( page( seq[i], i+1, num ) );
in_mem[ seq[i] ] = true ;
mem_pos[ num++ ] = seq[i] ;
if ( num >= MEM_SIZE ) is_full = true ;
}
}
///存储当前状态
for( int j=0; j<MEM_SIZE; j++ ) {
ret[i][j] = mem_pos[j] ;
}
}
return ret;
}
vector< vector<int> > LRU ( const vector< int > &seq , vector< bool > &is_miss ) {
vector< vector<int> > ret ;
Init( ret , is_miss , seq ) ;
vector< page > q ;
bool is_full = false ;
int num = 0, mem_pos[ MEM_SIZE ] = {0} ;
for( int i=0; i<seq.size(); i++ ) {
if ( in_mem[seq[i]] == false ) { // 不在 mem
is_miss[i] = true ;
if ( is_full == true ) { // mem已满,淘汰
page temp = q[0] ;
q[0] = page( seq[i], i+1, temp.pos ) ;
in_mem[ temp.val ] = false ; in_mem[ seq[i] ] = true ;
mem_pos[temp.pos] = seq[i] ;
}
else { // mem未满,添加
q.push_back( page( seq[i], i+1, num ) );
in_mem[ seq[i] ] = true ;
mem_pos[ num++ ] = seq[i] ;
if ( num >= MEM_SIZE ) is_full = true ;
}
}
else { // 在 mem
for( int i=0; i<q.size(); i++ ) {
if ( q[i].val == seq[i] ) {
q[i].prio = i ;
}
}
}
sort( q.begin() , q.end() ) ;
///存储当前状态
for( int j=0; j<MEM_SIZE; j++ ) {
ret[i][j] = mem_pos[j] ;
}
}
return ret;
}
vector< vector<int> > LFU ( const vector< int > &seq , vector< bool > &is_miss ) {
vector< vector<int> > ret ;
Init( ret , is_miss , seq ) ;
vector< page > q ;
bool is_full = false ;
int num = 0, mem_pos[ MEM_SIZE ] = {0} ;
for( int i=0; i<seq.size(); i++ ) {
if ( in_mem[seq[i]] == false ) { // 不在 mem
is_miss[i] = true ;
if ( is_full == true ) { // mem已满,淘汰
page temp = q[0] ;
q[0] = page( seq[i], 1, temp.pos ) ;
in_mem[ temp.val ] = false ; in_mem[ seq[i] ] = true ;
mem_pos[temp.pos] = seq[i] ;
}
else { // mem未满,添加
q.push_back( page( seq[i], 1, num ) );
in_mem[ seq[i] ] = true ;
mem_pos[ num++ ] = seq[i] ;
if ( num >= MEM_SIZE ) is_full = true ;
}
}
else { // 在 mem
for( int i=0; i<q.size(); i++ ) {
if ( q[i].val == seq[i] ) {
q[i].prio++ ;
break ;
}
}
}
sort( q.begin() , q.end() ) ;
///存储当前状态
for( int j=0; j<MEM_SIZE; j++ ) {
ret[i][j] = mem_pos[j] ;
}
}
return ret;
}
vector< vector<int> > NRU ( const vector< int > &seq , vector< bool > &is_miss ) {
double T_start, T_end ;
T_start = clock() ;
vector< vector<int> > ret ;
Init( ret , is_miss , seq ) ;
vector< page > q ;
bool is_full = false ;
int num = 0, mem_pos[ MEM_SIZE ] = {0} , prio[ PAGE_NUM ] = {0} ;
for( int i=0; i<seq.size(); i++ ) {
if ( in_mem[seq[i]] == false ) { // 不在 mem
is_miss[i] = true ;
if ( is_full == true ) { // mem已满,淘汰
page temp = q[0] ; in_mem[ temp.val ] = false ;
q[0] = page( seq[i], 0, temp.pos ) ; in_mem[ seq[i] ] = true ;
prio[ seq[i] ] |= 1 ; // 视为修改
mem_pos[temp.pos] = seq[i] ;
}
else { // mem未满,添加
q.push_back( page( seq[i], 0, num ) );
prio[ seq[i] ] |= 2 ; // 视为访问
in_mem[ seq[i] ] = true ;
mem_pos[ num ] = seq[i] ;
num++;
if ( num >= MEM_SIZE ) is_full = true ;
}
}
else { // 在 mem
prio[ seq[i] ] |= 2 ; // 视为访问
}
if ( clock() - T_start > NRU_LIMIT ) { // 更新
T_start = clock() ;
for( int i=0; i<PAGE_NUM; i++ ) {
prio[i] &= 1 ;
}
}
for( int i=0; i<q.size(); i++ ) {
q[i].prio = prio[ q[i].val ] ;
}
sort( q.begin() , q.end() ) ;
///存储当前状态
for( int j=0; j<MEM_SIZE; j++ ) {
ret[i][j] = mem_pos[j] ;
}
}
return ret;
}
void PrintTable ( const vector< vector<int> > &ans , const vector< bool > &is_miss , string type ) {
int num = 0 ;
printf( "%s\n", type.c_str() ) ;
for( int i=0; i<MEM_SIZE ; i++ ) {
printf( "\tmem unit %d :\t", i ) ;
for( int j=0; j<ans.size(); j++ ) {
if ( ans[j][i] != 0 ) {
printf( "%3d", ans[j][i] ) ;
}
else {
printf( " " ) ;
}
}
printf( "\n" ) ;
}
printf( "\tis miss :\t") ;
for( int i=0; i<is_miss.size(); i++ ) {
if ( is_miss[i] == true ) {
num++ ;
printf( " Y" ) ;
}
else {
printf( " N" ) ;
}
}
printf( "\n miss num : %d \n", num ) ;
}
const string type[4] = { "FIFO", "LRU", "LFU", "NRU" };
int main() {
vector< int > seq = CreatSeq( 19 ) ;
printf( "page seq:\t" ) ;
for( int i=0; i<seq.size(); i++ ) {
printf( "%3d", seq[i] ) ;
}
printf( "\n" ) ;
vector< bool > is_miss ;
///FIFO:
vector< vector < int > > ans_FIFO = FIFO( seq , is_miss ) ;
PrintTable( ans_FIFO , is_miss , type[0] ) ;
///LRU:
vector< vector < int > > ans_LRU = LRU( seq , is_miss ) ;
PrintTable( ans_LRU , is_miss , type[1] ) ;
///LFU:
vector< vector < int > > ans_LFU = LFU( seq , is_miss ) ;
PrintTable( ans_LFU , is_miss , type[2] ) ;
///NRU:
vector< vector < int > > ans_NRU = NRU( seq , is_miss ) ;
PrintTable( ans_NRU , is_miss , type[3] ) ;
return 0;
}
五、运行结果:
六、实验总结:
通过编程模拟四个页面淘汰算法的操作,实际了解了四个算法的淘汰方法以及核心思路,更了解了他们之间的关系和不同点。通过输入不同的数据比较四种方法的效率,确定的他们适用的情况。