操作系统:实验五内存管理实验

一、实验目的

1、了解操作系统动态分区存储管理过程和方法。

2、掌握动态分区存储管理的主要数据结构--空闲表区。

3、加深理解动态分区存储管理中内存的分配和回收。

4、掌握空闲区表中空闲区3种不同放置策略的基本思想和实现过程。

5、通过模拟程序实现动态分区存储管理。

6、了解请求分页虚拟存储管理技术的方法和特点。

7、通过模拟实现请求页式存储管理的几种基本页面置换算法。

8、掌握页面置换算法种缺页率、置换率和命中率的计算方法。

、实验内容

1、编程模拟实现动态分区管理中内存的分配和回收及空闲区表的管理。(2分)

首次适应算法(First Fit)参考程序:

#include<unistd.h>

#include<stdio.h>

#include<stdlib.h>

#define N 5

struct freearea

{

    int startaddr;  //空闲区起始地址

    int size;      //空闲区大小

    int state;     //1表示空闲,0表示占用

}freeblock[N]={{20,20,1},{80,50,1},{150,100,1},{300,30,1},{600,100,1}};

int alloc(int size)

{

    int i,tag=0,allocaddr;

    for(i=0;i<N;i++)

    {

        if(freeblock[i].state==1 && freeblock[i].size>size) //申请空间小于空闲空间

        {

           allocaddr=freeblock[i].startaddr;   //作业地址

           freeblock[i].startaddr+=size;   //新空闲区起始地址

           freeblock[i].size-=size;       //新空闲区大小

           tag=1;  //分配标记

           break;

        }

        else if(freeblock[i].state==1 && freeblock[i].size==size)//申请空间正好等于空闲空间

        {

           allocaddr=freeblock[i].startaddr;

           freeblock[i].state=0;tag=1;

           break;

        }

    }

    if(tag==0)  //表示没找到合适的空闲区,未分配内存

        allocaddr=-1;

    return allocaddr; //返回作业地址

}



void setfree(int addr,int size) //传过来的参数是要释放内存的起始地址和大小

{

    int i,tag1=0,tag2=0,n1=0,n2=0;

    for(i=0;i<N;i++)

    {

        if(freeblock[i].startaddr+freeblock[i].size==addr && freeblock[i].state==1)

        {

           tag1=1;     //有上邻标记

           n1=i;   //记录上邻数组位置(分区号)

           break;

        }

    }

    for(i=0;i<N;i++)

    {

        if(freeblock[i].startaddr==addr+size && freeblock[i].state==1) 

        {

           tag2=1;     //有下邻标记

           n2=i;   //记录下邻数组位置(分区号)

           break;

        }

    }      

    if(tag1==1 && tag2==0)  //有上邻无下邻

    {

        freeblock[n1].size+=size;

    }

    else if(tag1==1 && tag2==1) //有上邻有下邻

    {

           freeblock[n1].size+=freeblock[n2].size+size;

           freeblock[n2].state=0;//???

    }

    else if(tag1==0 && tag2==1) //无上邻有下邻

    {

        freeblock[n2].startaddr=addr;

        freeblock[n2].size+=size;

    }

    else    //无上邻无下邻(表明空间正好全部分配出去,空间的状态为0)

    {

        for(i=0;i<N;i++)

        {

           if(freeblock[i].state==0)   //通过空间状态值找到这块空间

           {

               freeblock[i].startaddr=addr;

               freeblock[i].size=size;

               freeblock[i].state=1;

               break;

           }

        }

    }

}



void adjust()

{

    int i,j;

    struct freearea temp;

    for(i=1;i<N;i++)    //依据首次适应算法将空闲区按起始地址由低到高冒泡排序

    {

        for(j=0;j<N-i;j++)

        {

           if(freeblock[j].startaddr>freeblock[j+1].startaddr)

           {

               temp=freeblock[j];

               freeblock[j]=freeblock[j+1];

               freeblock[j+1]=temp;

           }

        }

    }

    for(i=1;i<N;i++)    //把状态为0的排到后面

    {

        for(j=0;j<N-i;j++)

        {

           if(freeblock[j].state==0 && freeblock[j+1].state==1)

           {

               temp=freeblock[j];

               freeblock[j]=freeblock[j+1];

               freeblock[j+1]=temp;

           }

        }

    }

}

void print()

{

    int i;

    printf("\t|-------------------------------|\n");

    printf("\t|startaddr    size      state |\n");

    for(i=0;i<N;i++)

    printf("\t|%4d     %4d   %4d |\n",freeblock[i].startaddr,freeblock[i].size,freeblock[i].state);   

}



int main()

{

    int size,addr;

    char c1,c2,c;

    printf("At first the free memory is this:\n");//首先,空闲区是这样的

    adjust();

    print();   

    printf("Is there any job request memory?(y or n):");//有作业需要申请内存么?

    while((c1=getchar())=='y')

    {

        printf("Input request memory size:"); //输入所需内存大小

        scanf("%d",&size);

        addr=alloc(size); //调用内存分配函数,返回的是作业的起始地址

        if(addr==-1)

           printf("There is no fit memory.Please wait!!!\n");

        else

        {

           printf("Job's memory start address is:%d\n",addr);    //输出作业的起始地址

           printf("Job's size is:%d\n",size);  //输出作业大小

           printf("After allocation the free memory is this:\n");    //分配后可用内存如下:         adjust();

           print();

           printf("Job is running.\n");

        }

        getchar();

        printf("Is there any memory for free?(y or n):");//有需要释放的内存么?

        while((c2=getchar())=='y')

        {

           printf("Input free area startaddress:");

           scanf("%d",&addr);  //输入要释放内存的起始地址

           printf("Input free area size:");

           scanf("%d",&size);  //输入要释放内存的大小

           setfree(addr,size); //调用释放内存函数

           adjust();

           print();

           getchar();

           printf("Is there any memory for free?(y or n):");      

        }

        getchar();

        printf("Is there any job request memory?(y or n):");

    }

    return 0;  

}

运行结果截屏(包含分配和回收两部分):

分析该程序,列出各模块实现的功能:

1)alloc()

alloc() 函数为作业请求分配内存空间,从预定义的空闲内存块中找到合适的块并进行分配。

当程序检测到有作业请求内存时,通过调用 alloc(size) 函数来尝试分配指定大小 size 的内存空间。

alloc() 函数会遍历预定义的空闲内存块列表 freeblock[N],寻找第一个满足条件的空闲块:

  空闲状态为 1(表示可用)。

  大小大于或等于请求的 size。

如果找到合适的空闲块,alloc() 函数将更新该空闲块的状态和大小,标记为已分配(state = 0),并返回分配的作业内存块的起始地址。

如果无法找到满足请求的合适空闲块(即所有空闲块都无法容纳该作业),则 alloc() 函数返回 -1,表示分配失败。

alloc() 函数是整个内存管理系统中的核心部分,负责有效地管理和分配可用内存块。

它实现了简单的首次适应(first-fit)算法,根据作业的内存请求,将空闲块分配给作业,以满足程序的内存需求。

在主程序中,当作业请求内存时,会调用 alloc() 函数进行内存分配,并根据分配的结果执行相应的处理逻辑(如打印分配结果、更新空闲内存块列表等)。

alloc() 函数的返回值决定了作业请求内存的成功与否,从而影响程序的后续流程和作业的执行状态。

2)setfree()

setfree() 函数释放已占用的内存块,将其重新标记为可用的空闲内存块,并进行必要的空闲内存块合并操作。

当程序检测到作业不再需要某块内存时(例如作业执行完毕),会调用 setfree(addr, size) 函数来释放该作业占用的内存空间。

addr 参数表示要释放的内存块的起始地址,size 参数表示要释放的内存块的大小。

setfree() 函数首先会查找要释放的内存块是否与其他空闲内存块相邻,从而决定如何合并空闲块或创建新的空闲块。

通过遍历空闲内存块列表 freeblock[N],检查是否存在相邻的空闲块,以确定合并的方式。

如果要释放的内存块与某个空闲块相邻(上下邻接),则 setfree() 函数会将这些相邻的空闲块合并为一个更大的空闲块。

这样可以最大程度地利用内存空间,减少碎片化。

根据释放的内存块位置和大小,更新空闲块列表 freeblock[N] 中对应块的状态和大小。

将原来被占用的内存块重新标记为可用的空闲块(state = 1)。

在合并或释放后,可能会导致空闲块列表 freeblock[N] 中的顺序发生变化,因此需要调用 adjust() 函数对空闲块列表进行重新排序和调整,以便后续的内存分配能够高效地找到合适的空闲块。

3) adjust()

adjust() 函数对空闲内存块列表 freeblock[N] 进行调整和排序,以确保空闲内存块按照一定的规则进行管理和利用。

adjust() 函数实现了对空闲内存块的排序功能,将空闲块按照起始地址从小到大的顺序进行排列。

通过使用冒泡排序算法或类似的方法,将空闲内存块列表 freeblock[N] 中的元素按照起始地址升序进行排列,以便后续的内存分配和管理能够更高效地进行。

在排序的过程中,adjust() 函数也会根据空闲块的状态进行调整,确保已分配的内存块(state = 0)排在未分配的内存块(state = 1)之后。

这样可以提高内存分配算法的效率,例如首次适应算法(first-fit),从而更快地找到合适的空闲块来满足作业的内存需求。

adjust() 函数可能会通过合并相邻的空闲块来减少内存碎片化,使得空闲内存块更加紧凑和连续。

这样可以提高内存利用率,减少因内存碎片而导致无法分配大内存块的情况,从而优化内存资源的管理和利用。

在程序运行过程中,空闲内存块的状态会不断发生变化(分配、释放),因此需要定期调用 adjust() 函数对空闲内存块列表进行更新和调整,以保持其正确的顺序和状态。

这样可以确保内存分配算法能够在正确的基础上进行,提高系统的性能和稳定性。

2.修改上题,用最佳适应算法和最坏适应算法模拟内存空间的分配和回收。(4分)

注:只需列出程序不同部分,无需将整个程序列出。

(1)最佳适应算法

int alloc(int size)

{

    int i, tag = 0, allocaddr = -1;

    int min_size = INT_MAX; // 记录最小空闲区大小

    int best_fit_index = -1; // 记录最佳适配的空闲区索引



    for (i = 0; i < N; i++)

    {

        if (freeblock[i].state == 1 && freeblock[i].size >= size)

        {

           if (freeblock[i].size < min_size) // 找到更小的合适空闲区

           {

               min_size = freeblock[i].size;

               best_fit_index = i;

           }

        }

    }



    if (best_fit_index != -1)

    {

        allocaddr = freeblock[best_fit_index].startaddr; // 作业地址

        if (freeblock[best_fit_index].size > size) // 空闲区大于请求大小

        {

           freeblock[best_fit_index].startaddr += size; // 新空闲区起始地址

           freeblock[best_fit_index].size -= size;     // 新空闲区大小

        }

        else // 空闲区大小等于请求大小

        {

           freeblock[best_fit_index].state = 0; // 标记为占用

        }

        tag = 1; // 分配标记

    }



    return allocaddr; // 返回作业地址或-1(未分配)

}

(2)最坏适应算法

int alloc(int size)

{

    int i, tag = 0, allocaddr = -1;

    int max_size = -1; // 记录最大空闲区大小

    int worst_fit_index = -1; // 记录最坏适配的空闲区索引



    for (i = 0; i < N; i++)

    {

        if (freeblock[i].state == 1 && freeblock[i].size >= size)

        {

           if (freeblock[i].size > max_size) // 找到更大的合适空闲区

           {

               max_size = freeblock[i].size;

               worst_fit_index = i;

           }

        }

    }



    if (worst_fit_index != -1)

    {

        allocaddr = freeblock[worst_fit_index].startaddr; // 作业地址

        if (freeblock[worst_fit_index].size > size) // 空闲区大于请求大小

        {

           freeblock[worst_fit_index].startaddr += size; // 新空闲区起始地址

           freeblock[worst_fit_index].size -= size;     // 新空闲区大小

        }

        else // 空闲区大小等于请求大小

        {

           freeblock[worst_fit_index].state = 0; // 标记为占用

        }

        tag = 1; // 分配标记

    }



    return allocaddr; // 返回作业地址或-1(未分配)

}

3.编写程序实现先进先出页面置换算法,并计算缺页次数,缺页率,置换次数和命中率。(2分)

参考程序:

#include <stdio.h>

//初始化内存队列

void initializeList(int list[],int number){

    int i;

    for (i = 0; i < number; i ++) {

        list[i] = -1;

    }

}



//展示要访问页面号数组

void showList(int list[], int number){

    int i;

    for (i = 0; i < number; i ++) {

        printf("%2d",list[i]);

    }

    printf("\n");

}



//展示当前内存状态

void showMemoryList(int list[],int phyBlockNum){

    int i;

    for (i = 0; i < phyBlockNum; i ++) {

        if (list[i] == -1) {

            break;

        }

        printf(" |%d|",list[i]);

    }

    printf("\n");

}



//计算各项指标

void informationCount(int missingCount,int replaceCount,int pageNum){

    printf("缺页次数:%d   缺页率:%d/%d\n",missingCount,missingCount,pageNum);

    double result = (double)(pageNum - missingCount)/(double)pageNum;

    printf("置换次数:%d  命中率:%.2f\n",replaceCount,result);

}



//先进先出置换算法

void replacePageByFIFO(int memoryList[],int phyNum,int strList[],int pageNum){

    //置换次数

    int replaceCount = 0;

    //缺页次数

    int missingCount = 0;

    //记录当前最早进入内存的下标

    int pointer = 0;

  

//记录当前页面的访问情况: 0 未访问

int i,j,isVisited = 0;



    for (i = 0; i < pageNum; i ++) {

        isVisited = 0;

        //判断是否需要置换->内存已满且需要访问的页面不在内存中

        for (j = 0; j < phyNum; j ++) {

            if (memoryList[j] == strList[i]) {

                //该页面已经存在内存中

                //修改访问情况

                isVisited = 1;

                //展示

                printf("%d\n",strList[i]);

                break;

            }

            if (memoryList[j] == -1) {

                //页面不在内存中且内存未满->直接存入

                memoryList[j] = strList[i];

                //修改访问情况

                isVisited = 1;

                missingCount ++;

                //展示

                printf("%d\n",strList[i]);

                showMemoryList(memoryList, phyNum);

                break;

            }

        }

        if (!isVisited) {

            //当前页面还未被访问过->需要进行页面置换

            //直接把这个页面存到所记录的下标中

            memoryList[pointer] = strList[i];

            //下标指向下一个

            pointer ++;

            //如果到了最后一个,将下标归零

            if (pointer > phyNum-1) {

                pointer = 0;

            }          

            missingCount ++;

            replaceCount ++;

            //展示

            printf("%d\n",strList[i]);

            showMemoryList(memoryList, phyNum);

        }

    }

    informationCount(missingCount, replaceCount, pageNum);//计算各项指标

}



int main(int argc, const char * argv[]) { 



//物理块的数量

    int phyBlockNum;

    printf("请输入物理块数量:\n");

scanf("%d",&phyBlockNum);



    //生成内存队列数组

int memoryList[phyBlockNum];



    //初始化内存状态

    initializeList(memoryList, phyBlockNum);

//showMemoryList(memoryList,phyBlockNum);



    //页面数量

    int pageNum;

    printf("请输入要访问的页面总数:\n");

scanf("%d",&pageNum);



    //保存页面号数组

    int pageNumStrList[pageNum];

    int i;



//将要访问的页面号存入数组中

    printf("请输入要访问的页面号:\n");

    for (i = 0; i < pageNum; i ++) {

        scanf("%d",&pageNumStrList[i]);

}



    //显示要访问页面号数组中内容

showList(pageNumStrList, pageNum);



    int chose;

    while (1) {

        printf("请选择所需的置换算法:\n");

        printf("1.FIFO 2.退出\n");

        scanf("%d",&chose);

       

        switch (chose) {

            case 1:

//显示要访问页面号数组中内容

                showList(pageNumStrList, pageNum);

//调用先进先出置换算法

                replacePageByFIFO(memoryList, phyBlockNum, pageNumStrList, pageNum);

                //重新初始化内存

                initializeList(memoryList , phyBlockNum);

                break;

            default:

                return 0;

                break;

        }

    }   

    return 0;

}

编译及执行过程以及结果截屏:

分析程序功能:

这段程序是一个模拟页面置换算法(以 FIFO 算法为例)的简单内存管理系统。初始化内存队列

initializeList() 函数用于初始化内存队列 memoryList,将其所有元素都设置为 -1,表示内存块为空闲状态。

展示要访问页面号数组

showList() 函数用于展示要访问的页面号数组 pageNumStrList 中的内容。

展示当前内存状态

showMemoryList() 函数用于展示当前内存队列 memoryList 的状态,即展示内存中存储的页面号。

计算各项指标

informationCount() 函数用于根据缺页次数和置换次数计算缺页率和命中率,并将计算结果输出。

先进先出置换算法

replacePageByFIFO() 函数实现了先进先出(FIFO)页面置换算法:

使用循环遍历要访问的页面号数组 pageNumStrList。

判断页面是否在内存中:

如果页面已经在内存中,表示发生了页面命中。

如果页面不在内存中,需要进行页面置换:

将页面存入当前最早进入内存的位置,并将指针指向下一个位置(如果到达内存队列末尾则循环回到开头)。

计算缺页次数和置换次数,并展示内存状态。

主函数 main()

主函数负责用户交互和调用置换算法:

获取用户输入的物理块数量和要访问的页面号数组。

循环显示页面号数组和提供置换算法选择菜单。

根据用户选择调用相应的页面置换算法,并在每次置换后重新初始化内存状态。

该程序可以通过用户输入物理块数量、要访问的页面号数组和选择置换算法来模拟内存管理过程,并计算出缺页率和命中率等指标,用于简单地展示页面置换算法的工作原理和效果。

4.编程实现其它页面置换算法(如最近最久未使用算法或最佳置换算法等),计算缺页次数,缺页率,置换次数和命中率。(1分)

#include <stdio.h>

#include <stdlib.h>

#include <stdbool.h>



#define MAX_PHYSICAL_BLOCKS 10



// 初始化内存状态

void initializeMemory(int memoryList[], int phyBlockNum) {

    int i;

    for (i = 0; i < phyBlockNum; i++) {

        memoryList[i] = -1; // -1 表示内存块为空闲

    }

}



// 打印要访问的页面号数组

void showPageList(int pageNumStrList[], int pageNum) {

    printf("要访问的页面号序列:");

    for (int i = 0; i < pageNum; i++) {

        printf("%2d", pageNumStrList[i]);

    }

    printf("\n");

}



// 打印当前内存状态

void showMemoryList(int memoryList[], int phyBlockNum) {

    printf("当前内存状态:");

    for (int i = 0; i < phyBlockNum; i++) {

        if (memoryList[i] == -1) {

            printf("|  |");

        } else {

            printf("|%2d|", memoryList[i]);

        }

    }

    printf("\n");

}



// 计算缺页次数、缺页率、置换次数和命中率

void calculateMetrics(int missingCount, int replaceCount, int pageNum) {

    printf("缺页次数:%d   缺页率:%d/%d\n", missingCount, missingCount, pageNum);

    double hitRate = (double)(pageNum - missingCount) / (double)pageNum * 100.0;

    printf("置换次数:%d   命中率:%.2f%%\n", replaceCount, hitRate);

}



// LRU页面置换算法

void replacePageByLRU(int memoryList[], int phyNum, int strList[], int pageNum) {

    int missingCount = 0;

    int replaceCount = -phyNum;

    int counter[MAX_PHYSICAL_BLOCKS] = {0}; // 访问计数器数组,初始化为0



    for (int i = 0; i < pageNum; i++) {

        int page = strList[i];

        bool pageFound = false;



        // 查找页面是否在物理内存中

        for (int j = 0; j < phyNum; j++) {

            if (memoryList[j] == page) {

                pageFound = true;

                counter[j] = i + 1; // 更新访问计数器为当前访问的位置,+1避免计数器为0的情况

                printf("%d\n", page);

                break;

            }

        }



        if (!pageFound) {

            missingCount++; // 缺页



            // 查找最久未使用的页面进行置换

            int replaceIndex = 0;

            int minCounter = counter[0];

            for (int j = 1; j < phyNum; j++) {

                if (counter[j] < minCounter) {

                    minCounter = counter[j];

                    replaceIndex = j;

                }

            }



            // 置换页面

            memoryList[replaceIndex] = page;

            counter[replaceIndex] = i + 1; // 更新计数器

            replaceCount++;

            printf("%d\n", page);

            showMemoryList(memoryList, phyNum);

        }

    }



    calculateMetrics(missingCount, replaceCount, pageNum); // 计算缺页次数、缺页率、置换次数和命中率

}



int main() {

    int phyBlockNum;

    printf("请输入物理块数量:\n");

    scanf("%d", &phyBlockNum);



    int memoryList[MAX_PHYSICAL_BLOCKS];

    initializeMemory(memoryList, phyBlockNum);



    int pageNum;

    printf("请输入要访问的页面总数:\n");

    scanf("%d", &pageNum);



    int pageNumStrList[pageNum];

    printf("请输入要访问的页面号:\n");

    for (int i = 0; i < pageNum; i++) {

        scanf("%d", &pageNumStrList[i]);

    }



    showPageList(pageNumStrList, pageNum);



    int choice;

    while (1) {

        printf("请选择页面置换算法:\n");

        printf("1. LRU算法\n");

        printf("2. 退出\n");

        scanf("%d", &choice);



        switch (choice) {

            case 1:

                showPageList(pageNumStrList, pageNum);

                replacePageByLRU(memoryList, phyBlockNum, pageNumStrList, pageNum);

                initializeMemory(memoryList, phyBlockNum); // 重置内存状态

                break;

            default:

                return 0;

        }

    }



    return 0;

}

5.编程用动态分区链形式模拟动态分区管理中内存的分配和回收,采用3种算法(首次适应算法,最佳适应算法,最坏适应算法)实现。(附加题)

#include <stdio.h>

#include <stdlib.h>



#define N 5



// 定义空闲区结构体

struct FreeArea {

    int startAddr;  // 空闲区起始地址

    int size;       // 空闲区大小

    int state;      // 1表示空闲,0表示占用

};



// 初始的空闲区列表

struct FreeArea freeBlock[N] = {

    {20, 20, 1},

    {80, 50, 1},

    {150, 100, 1},

    {300, 30, 1},

    {600, 100, 1}

};



// 首次适应算法分配内存

int firstFit(int size) {

    int i, allocAddr = -1;

    for (i = 0; i < N; i++) {

        if (freeBlock[i].state == 1 && freeBlock[i].size >= size) {

            allocAddr = freeBlock[i].startAddr;

            if (freeBlock[i].size == size) {

                freeBlock[i].state = 0; // 分配整个空闲区

            } else {

                freeBlock[i].startAddr += size;

                freeBlock[i].size -= size;

            }

            break;

        }

    }

    return allocAddr;

}



// 最佳适应算法分配内存

int bestFit(int size) {

    int i, bestIndex = -1, minSize = 9999999;

    for (i = 0; i < N; i++) {

        if (freeBlock[i].state == 1 && freeBlock[i].size >= size) {

            if (freeBlock[i].size < minSize) {

                minSize = freeBlock[i].size;

                bestIndex = i;

            }

        }

    }

    if (bestIndex != -1) {

        int allocAddr = freeBlock[bestIndex].startAddr;

        if (freeBlock[bestIndex].size == size) {

            freeBlock[bestIndex].state = 0; // 分配整个空闲区

        } else {

            freeBlock[bestIndex].startAddr += size;

            freeBlock[bestIndex].size -= size;

        }

        return allocAddr;

    }

    return -1;

}



// 最坏适应算法分配内存

int worstFit(int size) {

    int i, worstIndex = -1, maxSize = -1;

    for (i = 0; i < N; i++) {

        if (freeBlock[i].state == 1 && freeBlock[i].size >= size) {

            if (freeBlock[i].size > maxSize) {

                maxSize = freeBlock[i].size;

                worstIndex = i;

            }

        }

    }

    if (worstIndex != -1) {

        int allocAddr = freeBlock[worstIndex].startAddr;

        if (freeBlock[worstIndex].size == size) {

            freeBlock[worstIndex].state = 0; // 分配整个空闲区

        } else {

            freeBlock[worstIndex].startAddr += size;

            freeBlock[worstIndex].size -= size;

        }

        return allocAddr;

    }

    return -1;

}



// 释放内存块

void setFree(int addr, int size) {

    int i;

    for (i = 0; i < N; i++) {

        if (freeBlock[i].startAddr + freeBlock[i].size == addr && freeBlock[i].state == 1) {

            freeBlock[i].size += size;

            break;

        }

    }

    for (i = 0; i < N; i++) {

        if (freeBlock[i].startAddr == addr + size && freeBlock[i].state == 1) {

            freeBlock[i].startAddr = addr;

            freeBlock[i].size += size;

            break;

        }

    }

    for (i = 0; i < N; i++) {

        if (freeBlock[i].state == 0) {

            if (freeBlock[i + 1].state == 1) {

                freeBlock[i].size += freeBlock[i + 1].size;

            }

        }

    }

}



// 调整空闲区链表

void adjust() {

    int i, j;

    struct FreeArea temp;

    for (i = 1; i < N; i++) {

        for (j = 0; j < N - i; j++) {

            if (freeBlock[j].startAddr > freeBlock[j + 1].startAddr) {

                temp = freeBlock[j];

                freeBlock[j] = freeBlock[j + 1];

                freeBlock[j + 1] = temp;

            }

        }

    }

}



// 打印空闲区信息

void print() {

    int i;

    printf("\t|-------------------------------|\n");

    printf("\t|起始地址    大小       状态     |\n");

    for (i = 0; i < N; i++) {

        printf("\t|%4d        %4d       %4d      |\n", freeBlock[i].startAddr, freeBlock[i].size, freeBlock[i].state);

    }

}



int main() {

    int size, addr;

    char choice;

    printf("初始空闲内存状态如下:\n");

    adjust();

    print();



    do {

        printf("请选择内存分配算法:\n");

        printf("1. 首次适应算法\n");

        printf("2. 最佳适应算法\n");

        printf("3. 最坏适应算法\n");

        printf("4. 退出\n");

        printf("请输入选项(1-4):");

        scanf(" %c", &choice);



        switch (choice) {

            case '1':

                printf("请输入作业的内存大小:");

                scanf("%d", &size);

                addr = firstFit(size);

                break;

            case '2':

                printf("请输入作业的内存大小:");

                scanf("%d", &size);

                addr = bestFit(size);

                break;

            case '3':

                printf("请输入作业的内存大小:");

                scanf("%d", &size);

                addr = worstFit(size);

                break;

            case '4':

                printf("退出程序。\n");

                return 0;

            default:

                printf("无效的选项,请重新输入。\n");

                break;

        }



        if (choice >= '1' && choice <= '3') {

            if (addr == -1) {

                printf("无法分配所需内存。\n");

            } else {

                printf("作业分配的起始地址:%d\n", addr);

                printf("分配后的空闲内存状态:\n");

                adjust();

                print();



                // 释放内存

                printf("是否需要释放内存?(y或n):");

                scanf(" %c", &choice);

                while (choice == 'y') {

                    printf("请输入要释放的区域起始地址和大小:");

                    scanf("%d %d", &addr, &size);

                    setFree(addr, size);

                    adjust();

                    print();

                    printf("是否需要继续释放内存?(y或n):");

                    scanf(" %c", &choice);

                }

            }

        }

    } while (choice != '4');



    return 0;

}

三、实验总结和体会(1分)

本次学习中,你可以学到以下几个方面:

动态分区管理:学习了如何使用链表来模拟动态分区管理中的内存分配和回收过程。动态分区管理是一种常见的内存管理方式,适用于需要动态分配和回收内存空间的场景,比如操作系统中的内存分配。

内存分配算法:掌握了常见的内存分配算法,包括首次适应算法、最佳适应算法和最坏适应算法。这些算法针对不同的内存分配需求,选择合适的算法可以提高内存利用效率和系统性能。

数据结构与算法:通过实现动态分区管理算法,加深了对链表、循环、条件判断等基本数据结构和算法的理解和应用。

本次实验存在许多难点:

算法的选择和实现:需要理解并实现多种内存分配算法,包括不同算法的逻辑和具体操作步骤。链表的操作:使用链表来管理动态分区,需要熟练掌握链表的插入、删除等操作,确保内存分配和回收的准确性和高效性。用户交互的设计:设计用户友好的交互界面,能够准确捕捉用户的输入,并根据用户选择进行相应的操作和反馈,考验了程序设计的整体性和实用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值