Windows页面置换算法与文件操作

news2024/11/16 21:59:27

实验一

一、实验内容或题目:

随机产生页面访问序列,并实现LRU, FIFO, OPT三种算法进行缺页比较

二、实验目的与要求:

1、编写程序,随机产生页面访问序列,并实现LRU, FIFO, OPT三种算法进行缺页比较。
2、理解三种算法的机制及优劣点。
3、理解belady现象

三、实验步骤:

1、在pagefault.c基础上实现三种算法。
2、运行并比较三种算法的缺页次数
3、通过固定srand函数的种子,并调节MEMORY_SIZE大小以及随机实验,尝试让FIFO算法出现belady现象

四、实验结果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、总结:

由于期末临近,实在是没有时间来完成这个实验,在GitHub上找了一个作者的代码进行了阅读,LRU, FIFO, OPT三个算法思路还是比较清晰的,当然OPT是无法跑的,作者用了数据结构的方式来实现这三个方式,读起来有些复杂的,但思路还是很清晰的。如果自己写还是比较难写出来的,这个需要考虑的东西会很多,很容易出错。

算法规则特点
OPT优先淘汰最长时间内不会被访问的页面缺页率最小,性能最好,但无法实现
FIFO优先淘汰最先进入内存的页面实现简单,但性能很差,可能出现Belady异常
LRU优先淘汰最近最久没访问的页面性能很好,但需要硬件支持,算法开销大

Belady现象是指当进程分配的物理块数增大时,缺页次数不减反增的异常现象。

六、源码

#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <time.h>

#define total_instruction 320 //指令流长(指令数量)
#define total_vp 32 //虚页长(虚拟空间大小)
#define INVALID -1
#define TRUE 1
#define FALSE 0

#define clear_period 50 //清零周期(NUR)

typedef struct
{
    int pn; //page number
    int pfn; //page_frame number
    int counter; //访问记录(LFU、NUR)
    int time; //访问时间(LRU)
}pl_type;//页面结构体(进程)
pl_type pl[32];//32个虚存页面

typedef struct pfc_struct
{
    int pn, pfn;
    struct pfc_struct* next;
}pfc_type;//页框结构体(内存)
pfc_type pfc[32], * freepf_head, * busypf_head, * busypf_tail;

int diseffect; //缺页次数
int a[total_instruction]; //地址序列
int page[total_instruction]; //页号
int offset[total_instruction]; //页内偏移

void generate_inst_addr_sq() { //生成地址序列
    int s, i;
    srand(time(NULL)); //设置随机数种子

    s = (float)319 * rand() / RAND_MAX + 1; //0-319随机数
    for (i = 0; i < total_instruction; i += 4)
    {
        if (s < 0 || s>319)
        {
            printf("When i==%d, Error, s==%d\n", i, s);
            exit(0);
        }
        a[i] = s; //任意一指令访问点
        a[i + 1] = a[i] + 1; //顺序执行一条指令
        a[i + 2] = (float)a[i] * rand() / RAND_MAX; //执行前指令m
        a[i + 3] = a[i + 2] + 1; //顺序执行一条指令
        s = (float)(318 - a[i + 2]) * rand() / RAND_MAX + a[i + 2] + 2;
        if ((a[i + 2] > 318) || (s > 319))
            printf("a[%d+2], a number which is: %d and s==%d", i, a[i + 2], s);
    }
    for (i = 0; i < total_instruction; i += 4)
        printf("%03d, %03d, %03d, %03d\n", a[i], a[i + 1], a[i + 2], a[i + 3]);

    for (i = 0; i < total_instruction; i++)
    {//将地址转换为页号、页内偏移,每个页面大小为10
        page[i] = a[i] / 10;
        offset[i] = a[i] % 10;
    }
}

void initialize(int total_pf)
{
    int i;
    diseffect = 0;

    for (i = 0; i < 32; i++)
    {
        pl[i].pn = i;
        pl[i].pfn = INVALID;
        pl[i].counter = 0;
        pl[i].time = -1;
    }
    for (i = 0; i < total_pf - 1; i++)
    {
        pfc[i].next = &pfc[i + 1];
        pfc[i].pfn = i;
    }
    pfc[total_pf - 1].next = NULL;
    pfc[total_pf - 1].pfn = total_pf - 1;
    freepf_head = &pfc[0]; //freepf_head总是指向可用页框
}

void FIFO(int total_pf)
{
    int i, j;
    pfc_type* p;
    initialize(total_pf);
    busypf_head = busypf_tail = NULL;
    for (i = 0; i < total_instruction; i++)
    {
        if (pl[page[i]].pfn == INVALID)
        {
            diseffect += 1;
            if (freepf_head == NULL) //没有空闲页框
            {//释放忙页框队列中的第一个页面框
                p = busypf_head->next;
                pl[busypf_head->pn].pfn = INVALID; //原来页取消所在页框
                freepf_head = busypf_head;
                freepf_head->next = NULL; //处理p=freepf_head->next,之后保持没有空闲页框
                busypf_head = p; //更新忙页框队列起点
            }
            //freepf所示页框填入页面
            p = freepf_head->next; //暂存下一个可能空闲的页框
            freepf_head->next = NULL;
            freepf_head->pn = page[i];
            pl[page[i]].pfn = freepf_head->pfn;
            /*将freepf页框插入忙队列尾*/
            if (busypf_tail == NULL) //忙页框队列为空(仅执行一次)
                busypf_head = busypf_tail = freepf_head;
            else
            {
                busypf_tail->next = freepf_head;
                busypf_tail = freepf_head;
            }
            freepf_head = p;
        }
    }
    printf("FIFO:%6.4f ", 1 - (float)diseffect / 320);
}

void LRU(int total_pf)
{
    int min, minj, i, j, present_time;
    initialize(total_pf);
    present_time = 0;

    for (i = 0; i < total_instruction; i++)
    {
        if (pl[page[i]].pfn == INVALID)
        {
            diseffect++;
            if (freepf_head == NULL) //没有空闲页框,需替换
            {   //找到time最小的页,并释放其页框
                min = 32767;
                for (j = 0; j < 32; j++)
                {
                    if (min > pl[j].time && pl[j].pfn != INVALID) //页框队列中time最小的页面
                    {
                        min = pl[j].time;
                        minj = j;
                    }
                }
                //其页框进入free_pf,撤销time最小的页面
                freepf_head = &pfc[pl[minj].pfn];
                pl[minj].pfn = INVALID;
                pl[minj].time = -1;
                freepf_head->next = NULL; //处理freepf_head=freepf_head->next,之后保持没有空闲页框
            }
            //新页换入freepf中的第一个页框
            pl[page[i]].pfn = freepf_head->pfn;
            pl[page[i]].time = present_time;
            freepf_head = freepf_head->next;
        }
        else
            pl[page[i]].time = present_time; //忙页框队列中命中,更新time
        present_time++;
    }
    printf("LRU:%6.4f ", 1 - (float)diseffect / 320);
}

void OPT(int total_pf)
{
    int i,j , max, maxpage, d, dist[total_vp];
    pfc_type *t;
    initialize(total_pf);
    for(i=0;i<total_instruction;i++)
    {
        if(pl[page[i]].pfn==INVALID)
        {
            diseffect++;
            if(freepf_head==NULL)
            {
                for(j=0;j<total_vp;j++)
                    if(pl[j].pfn!=INVALID)
                        dist[j]=32767;
                    else
                        dist[j]=0;
                d=1;
                for(j=i+1;j<total_instruction;j++)
                {
                    if(pl[page[j]].pfn!=INVALID)
                        dist[page[j]]=d;
                    d++;
                }
                max=-1;
                for(j=0;j<total_vp;j++)
                    if(max<dist[j])
                    {
                        max=dist[j];
                        maxpage=j;
                    }
                freepf_head=&pfc[pl[maxpage].pfn];
                freepf_head->next=NULL;
                pl[maxpage].pfn=INVALID;
            }
            pl[page[i]].pfn=freepf_head->pfn;
            freepf_head=freepf_head->next;
        }
    }
    printf("OPT:%6.4f ",1-(float)diseffect/320);
}


int main()
{
    int i;

    generate_inst_addr_sq();

    for (i = 4; i <= 32; i++) //物理内存容量:4-32个页框
    {
        printf("%2d page frames\t", i);
        FIFO(i);
        LRU(i);
        //OPT(i);
        printf("\n");
    }
    return 0;
}

实验二

一、实验内容或题目:

通用调用操作系统API,实现对文件的创建和异步读取操作。

二、实验目的与要求:

1、通用调用操作系统API,实现对文件的创建和异步读取操作
2、了调文件系统中的一些常用参数应用
3、编写程序实现并理解I/O设备的异步访问

三、实验步骤:

1、编写createAndExpandFile函数,在指定位置创建文件并扩展到1M长度
2、编写getFileContentAsync函数,异步读取文件内容。内容并无意义,读到缓冲区中即可,但要求使用异步读取,主函数在发起异步请求后等待在事件上,等异步完成后回调再唤醒。
需要使用的api:
CreateFile, SetEndOfFile, SetFilePointer, ReadFile, WaitEvent

四、实验结果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、总结

根据官网的指示,要使用SetEndOfFile才能实现文件的扩展。由于官网并没有给实例代码,查了很多资料才知道怎么写。通过将SetFilePointer调用到所需位置,然后通过SetEndOfFile截断到所需位置,就可以实现文件长度的扩展。
在这里插入图片描述
在这里插入图片描述
在第二个实验上,通过事件内核对象,可以支持多个异步io。每个read或者write里面的overlapped的结构,可以设置一个事件内核对象,这样每次io的事件内核对象是不一样的,就可以支持多个异步io了。

六、源码

#include <Windows.h>
#include <stdio.h>
#include <winerror.h>


#define FILE_NAMEA	TEXT(FILE_NAME)

HANDLE hEvent;

/**
在此函数中创建FILE_NAME并将之扩展到1MB大小
注意:
1)创建文件时使用TRUNCATE_EXSITING标识
2)传参时使用FILE_NAMEA
**/
void createAndExpandFile() {
	LPCTSTR lpfname = TEXT("C://Users//86133//Desktop//text.tmp");
	LONG lsize = 1000000; // 1MB
	DWORD dwErr;
	HANDLE file = CreateFile(lpfname,
		GENERIC_WRITE,
		FILE_SHARE_WRITE,
		NULL,
		CREATE_NEW | OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	dwErr = GetLastError();
	if (dwErr > 0) {
		printf("Error Code:%d", &dwErr);
	}
	SetFilePointer(file, lsize, 0, FILE_BEGIN);
	SetEndOfFile(file);
	CloseHandle(file);
}

/**
在此函数中打开创建的文件,读出其所有内容到一个缓冲区中
使用异步读,在读回调函数里使用hEvent通知主函数继续运行
**/
void getFileContentAsync() {
	HANDLE hFile = CreateFileW(L"C://Users//86133//Desktop//text.tmp", GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);//打开前面创建的文件
	BYTE buffer[10] = { 0 };
	OVERLAPPED ol = { 0 };
	ol.Offset = 0;
	HANDLE hEvent = CreateEvent(0, FALSE, FALSE, NULL);
	ol.hEvent = hEvent;//传递一个事件对象。

	BOOL rt = ReadFile(hFile, buffer, 7, NULL, &ol);//提交一个异步读操作

	if (rt == FALSE && GetLastError() == ERROR_IO_PENDING)
	{
		WaitForSingleObject(ol.hEvent, INFINITE);//等待事件对象被触发。
	}

	CloseHandle(hFile);
	CloseHandle(hEvent);
}

int main() {
	hEvent = CreateEvent(
		NULL,               // default security attributes
		TRUE,               // manual-reset event
		FALSE,              // initial state is nonsignaled
		NULL  // object name
	);
	createAndExpandFile();
	getFileContentAsync();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/676758.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自监督学习简介

1.  自监督学习 自监督学习是可以看做是一种特殊的无监督学习的一个子类别&#xff08;但并非无监督学习&#xff09;&#xff0c;因为它利用了未标记的数据。 关键思想是让模型无需手动标签即可学习数据表示。一旦模型学会了如何表示数据&#xff0c;那么它就可以用较少量的…

liunx+docker+rabbitmq安装延迟队列插件

安装版本 rabbit: RabbitMQ 3.8.16 erlang: Erlang 23.3.2 rabbit: rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez 准备 1.rabbmitMQ 安装 docker pull rabbitmq 2.rabbmitMQ 启动 docker run -d --hostname my-rabbit --name rabbit -e RABBITMQ_DEFAULT_USER用户…

10 种分布式系统必备模式

在当今的技术领域中&#xff0c;分布式系统已成为许多大型应用程序和平台的核心。构建高性能、可伸缩和可靠的分布式系统是一个复杂的挑战&#xff0c;需要合理的架构设计和模式选择。本文将介绍10个必备的分布式系统模式&#xff0c;帮助您更好地理解和应用这些模式以提升系统…

pytorch笔记:RNN 系列

来自B站视频&#xff0c;API查阅&#xff0c;TORCH.NN RNN可以处理变长序列&#xff0c;是因为其每个时刻的参数是共享的RNN每算出一个时刻都可以输出&#xff0c;适合流式输出&#xff0c;但串行计算比较慢&#xff0c;无法获取太长的历史信息RNN 初始隐状态不提供默认是0&am…

一、枚举类型——用枚举实现状态机

枚举类型很适合用来实现状态机。状态机可以处于有限数量的特定状态。它们通常根据输入&#xff0c;从一个状态移动到下一个状态&#xff0c;但同时也会存在瞬态。当任务执行完毕后&#xff0c;状态机会立即跳出所有状态。 每个状态都有某些可接受的输入&#xff0c;不同的输入…

你应该知道的 Python 自动化脚本

概要 我们都有一些需要重复做的任务。幸运的是&#xff0c;我们可以将其中一些过程自动化&#xff0c;这样我们就可以专注于做其他真正需要精力和注意力的事情。 在这篇文章中&#xff0c;我们将谈论一些 Python 自动化脚本&#xff0c;你可以轻松地用它们来执行自动化任务。重…

巨星内马尔为孕期出轨道歉了!喊话女友:“我不能想象失去你”

近日&#xff0c;巴西球星内马尔在女友布鲁娜孕期出轨的传闻引起了社会广泛关注。 22日凌晨&#xff0c;内马尔在自己的社交媒体上发文回应并道歉&#xff0c;表示自己在球场内外都会犯错&#xff0c;但私生活的问题他会在家里解决。 他还重申了自己已经为犯下的错误和不必要的…

python爬虫_函数的使用

文章目录 ⭐前言⭐python函数&#x1f496; 参数传递—值&#x1f496; 参数传递—引用&#x1f496; 多参数(*)&#x1f496;lambda匿名函数 结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于python函数入门使用。 该系列文章&#xff1a; python爬虫_基本数…

【031】C++类和对象之运算符重载详解和代码实践(最全讲解)

C类和对象之运算符重载详解 引言一、运算符重载的基本概念1.1、可重载的运算符1.2、不可重载的运算符 二、重载 << 运算符&#xff08;全局函数实现&#xff09;三、重载 >> 运算符&#xff08;全局函数实现&#xff09;四、重载 运算符4.1、全局函数实现4.2、成员…

leetcode257. 二叉树的所有路径(java)

二叉树的所有路径 leetcode257. 二叉树的所有路径题目描述DFS深度优先遍历 二叉树专题 leetcode257. 二叉树的所有路径 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/binary-tree-paths 题目描述 给你一个二叉树的根节…

【系统开发】尚硅谷 - 谷粒商城项目笔记(十一):K8S

文章目录 K8s简介架构原理核心概念控制平面组件&#xff08;Control Plane Components&#xff09;kube-apiserveretcdkube-schedulerkube-controller-managercloud-controller-manager Node 组件kubeletkube-proxy容器运行时&#xff08;Container Runtime&#xff09; 插件&a…

Gee 项目复现

序言 复现&#xff1a;原链接 一个Web框架需要支持的功能&#xff0c; 路由&#xff0c;请求到响应函数的映射&#xff0c;支持动态路由如hello/:name,hello/*模板&#xff0c;使用内置模板引擎渲染机制。鉴权&#xff1a;分组插件&#xff1a;中间件 第一天 HTTP基础 启动…

基于边界点优化和多步路径规划的机器人自主探索

论文题目&#xff1a;Autonomous Robotic Exploration Based on Frontier Point Optimization and Multistep Path Planning 中文题目&#xff1a;基于边界点优化和多步路径规划的机器人自主探索 作者&#xff1a;Baofu Fang &#xff1b;Jianfeng Ding ; Zaijun Wang 作者机…

5.5.2 IPv6数据报格式

5.5.2 IPv6数据报格式 首先我们来回忆一下IPv4数据报首部格式&#xff08;5.2.3 IP数据报&#xff08;一&#xff09;IP数据报的格式&#xff09;&#xff0c;包括20个字节的固定部分和长度可变的选项部分&#xff0c;如图 红色方框标注的是在IPv6中会消失的字段&#xff0c;椭…

小白也会的------新建Python虚拟环境,查看该虚拟环境的路径,将该虚拟环境的所有库和版本号导出到一个 requirements.txt 文件中

我的目录标题 1、新建Python虚拟环境2、查看该虚拟环境的路径3、将该虚拟环境的所有库和版本号导出到一个 requirements.txt 文件中4、如果你只需要将当前虚拟环境中安装的所有库和版本号导出到一个 requirements.txt 文件中&#xff0c;而不需要包括每个库的来源&#xff0c;可…

KMP算法基础

前言 KMP算法是我们数据结构串中最难也是最重要的算法。难是因为KMP算法的代码很优美简洁干练&#xff0c;但里面包含着非常深的思维。真正理解代码的人可以说对KMP算法的了解已经相当深入了。而且这个算法的不少东西的确不容易讲懂&#xff0c;很多正规的书本把概念一摆出直接…

C++——命名空间(namespace)

目录 1. C语言命名冲突 2. 命名空间定义 3. 命名空间使用 可能大家在看别人写的C代码中&#xff0c;在一开始会包这个头文件&#xff1a;#include<iostream> 这个头文件等价于我们在C语言学习到的#include<stdio.h>&#xff0c;它是用来跟我们的控制台输入和输出…

带你见见红黑树-概念+插入篇

写的不好&#xff0c;见谅~ 目录 概念理解 红黑树规则 AVL树与红黑树的相爱相杀 红黑树的插入时的上色与旋转。 不上色&#xff08;shǎi&#xff09; 情况一&#xff1a;空树 情况二&#xff1a;非空树&#xff0c;父节点为黑 上色&#xff08;shǎi&#xff09; 情况…

【Linux】深入理解文件系统

系列文章 收录于【Linux】文件系统 专栏 关于文件描述符与文件重定向的相关内容可以移步 文件描述符与重定向操作。 可以到 浅谈文件原理与操作 了解文件操作的系统接口。 想深入理解文件缓冲区还可以看看文件缓冲区。 目录 系列文章 磁盘 结构介绍 定位数据 抽象管理…

【Linux】MySQL 高级 SQL 语句 (二)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MySQL 高级 SQL 语句 连接查询CREATE VIEW 视图UNION 联集交集值无交集值CASE空值(NULL) 和 无值() 的区别正则表达式 连接查询 mysql> select * from xjz; #xjz表格 ---…