【操作系统】内存管理设计性实验报告

7 篇文章 1 订阅

操作系统#内存管理设计性实验报告

正文

一、 实验目的
1.通过本次试验体会操作系统中内存的分配模式;
2.掌握内存分配的方法(首次适应(FF),最佳适应(BF),最差适应(WF));
3.学会进程的建立,当一个进程被终止时内存是如何处理被释放块,并当内存不满足进程申请时是如何使用内存紧凑;
4.掌握内存回收过程及实现方法;
5.学会进行内存的申请释放和管理;

二、 实验设备

实验机房虚拟机里的中linux系统

三、 实验要求

1、运行如下的内存申请与释放序列:先设置内存大小为2048k,进程1申请500k,进程2申请300k,进程1完成,进程3申请200k,进程4申请100k,进程5申请300k;

2、分别选择不同的内存分配算法,输出上述序列的内存分配结果;

3、实现循环首次适应算法,并输出上述序列采用该分配算法后的结果。

四、 实验步骤

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>

#define PROCESS_NAME_LEN     32        /*进程名称的最大长度*/
#define MIN_SLICE            10        /*最小碎片的大小*/
#define DEFAULT_MEM_SIZE     1024      /*默认内存的大小*/
#define DEFAULT_MEM_START    0         /*默认内存的起始位置*/

/* 内存分配算法 */
#define MA_FF      1
#define MA_BF      2
#define MA_WF      3

int mem_size = DEFAULT_MEM_SIZE;         /*内存大小*/
int ma_algorithm = MA_FF;              /*当前分配算法*/
int flag = 0;            		       /*设置内存大小标志*/
static int pid = 0;                    /*初始pid*/
int algorithm;

/*描述每一个空闲块的数据结构*/
struct free_block_type {
    int size;
    int start_addr;
    struct free_block_type* next;
};


/*指向内存中空闲块链表的首指针*/
struct free_block_type* free_block;

/*每个进程分配到的内存块的描述*/
struct allocated_block {
    int pid;
    int size;
    int start_addr;
    char process_name[PROCESS_NAME_LEN];
    struct allocated_block* next;
};
/*进程分配内存块链表的首指针*/
struct allocated_block* allocated_block_head = NULL;

struct allocated_block* find_process(int id)
{
    struct allocated_block* p;
    p = allocated_block_head;
    while (p != NULL)
    {
        if (p->pid == id)
            p = p->next;
            return p;
    }
    return NULL;
}

void swap(int* p, int* q)
{
    int temp;

    temp = *p;
    *p = *q;
    *q = temp;

    return;
}

void do_exit()
{
    exit(0);
}

/*初始化空闲块,默认为一块,可以指定大小及起始地址*/
struct free_block_type* init_free_block(int mem_size) {
    struct free_block_type* fb;

    fb = (struct free_block_type*)malloc(sizeof(struct free_block_type));
    if (fb == NULL) {
        printf("No mem\n");
        return NULL;
    }
    fb->size = mem_size;
    fb->start_addr = DEFAULT_MEM_START;
    fb->next = NULL;
    return fb;
}

/*显示菜单*/
display_menu() {
    printf("\n");
    printf("1 - Set memory size (default=%d)\n", DEFAULT_MEM_SIZE);
    printf("2 - Select memory allocation algorithm\n");
    printf("3 - New process \n");
    printf("4 - Terminate a process \n");
    printf("5 - Display memory usage \n");
    printf("0 - Exit\n");
}

/*设置内存的大小*/
set_mem_size() {
    int size;
    if (flag != 0) {  //防止重复设置
        printf("Cannot set memory size again\n");
        return 0;
    }
    printf("Total memory size =");
    scanf("%d", &size);
    if (size > 0) {
        mem_size = size;
        free_block->size = mem_size;
    }
    flag = 1;  return 1;
}

/*按FF算法重新整理内存空闲块链表*/
rearrange_FF() {
    struct free_block_type* tmp, * work;
    printf("Rearrange free blocks for FF \n");
    tmp = free_block;
    while (tmp != NULL)
    {
        work = tmp->next;
        while (work != NULL) {
            if (work->start_addr > tmp->start_addr)
            { /*地址递增*/
                swap(&work->start_addr, &tmp->start_addr);
                swap(&work->size, &tmp->size);
            }

            work = work->next;
        }
        tmp = tmp->next;
    }
}

/*按BF最佳适应算法重新整理内存空闲块链表*/

rearrange_BF() {
    struct free_block_type* tmp, * work;
    printf("Rearrange free blocks for BF \n");
    tmp = free_block;
    while (tmp != NULL)
    {
        work = tmp->next;
        while (work != NULL) {
            if (work->size < tmp->size) { /*地址递增*/
                swap(&work->start_addr, &tmp->start_addr);
                swap(&work->size, &tmp->size);
            }

            work = work->next;
        }
        tmp = tmp->next;
    }
}


/*按WF算法重新整理内存空闲块链表*/

rearrange_WF() {
    struct free_block_type* tmp, * work;
    printf("Rearrange free blocks for WF \n");
    tmp = free_block;
    while (tmp != NULL)
    {
        work = tmp->next;
        while (work != NULL) {
            if (work->size < tmp->size) { /*地址递增*/
                swap(&work->start_addr, &tmp->start_addr);
                swap(&work->size, &tmp->size);
            }
            else
                work = work->next;
        }
        tmp = tmp->next;
    }
}

/*按指定的算法整理内存空闲块链表*/
rearrange(int algorithm) {
    switch (algorithm) {
    case MA_FF:  rearrange_FF(); break;
    case MA_BF:  rearrange_BF(); break;
    case MA_WF:  rearrange_WF(); break;
    }
}

/* 设置当前的分配算法 */
set_algorithm() {

    printf("\t1 - First Fit\n");
    printf("\t2 - Best Fit \n");
    printf("\t3 - Worst Fit \n");
    scanf("%d", &algorithm);
    if (algorithm >= 1 && algorithm <= 3) ma_algorithm = algorithm;
    //按指定算法重新排列空闲区链表
    rearrange(ma_algorithm);
}

/*分配内存模块*/
int allocate_mem(struct allocated_block* ab) {
    struct free_block_type* fbt, * pre, * temp, * work;
    int request_size = ab->size;
    fbt = free_block;
    while (fbt != NULL)
    {
        if (fbt->size >= request_size)
        {
            if (fbt->size - request_size >= MIN_SLICE) /*分配后空闲空间足够大,则分割*/
            {
                mem_size -= request_size;
                fbt->size -= request_size;
                ab->start_addr = fbt->start_addr;
                fbt->start_addr += request_size;
            }
            else  if (((fbt->size - request_size) < MIN_SLICE) && ((fbt->size - request_size) > 0))
                /*分割后空闲区成为小碎片,一起分配*/
            {
                mem_size -= fbt->size;
                pre = fbt->next;
                ab->start_addr = fbt->start_addr;
                fbt->start_addr += fbt->size;
                free(fbt);
            }
            else
            {
                temp = free_block;

                while (temp != NULL)
                {
                    work = temp->next;

                    if (work != NULL)/*如果当前空闲区与后面的空闲区相连,则合并*/
                    {
                        if (temp->start_addr + temp->size == work->start_addr)
                        {
                            temp->size += work->size;
                            temp->next = work->next;
                            free(work);
                            continue;
                        }
                    }

                    temp = temp->next;
                }

                fbt = free_block;
                break;
            }
            rearrange(algorithm); /*重新按当前的算法排列空闲区*/
            return 1;
        }

        pre = fbt;
        fbt = fbt->next;
    }
    return -1;
}

/*创建新的进程,主要是获取内存的申请数量*/
new_process() {
    struct allocated_block* ab;
    int size;
    int ret;
    ab = (struct allocated_block*)malloc(sizeof(struct allocated_block));
    if (!ab) exit(-5);
    ab->next = NULL;
    pid++;
    sprintf(ab->process_name, "PROCESS-%02d", pid);
    ab->pid = pid;

    printf("Memory for %s:", ab->process_name);
    scanf("%d", &size);
    if (size > 0) ab->size = size;
    ret = allocate_mem(ab);  /* 从空闲区分配内存,ret==1表示分配ok*/
/*如果此时allocated_block_head尚未赋值,则赋值*/
    if ((ret == 1) && (allocated_block_head == NULL)) {
        allocated_block_head = ab;
        return 1;
    }
    /*分配成功,将该已分配块的描述插入已分配链表*/
    else if (ret == 1) {
        ab->next = allocated_block_head;
        allocated_block_head = ab;
        return 2;
    }
    else if (ret == -1) { /*分配不成功*/
        printf("Allocation fail\n");
        free(ab);
        return -1;
    }
    return 3;
}

/*将ab所表示的已分配区归还,并进行可能的合并*/
int free_mem(struct allocated_block* ab)
{
    int algorithm = ma_algorithm;
    struct free_block_type* fbt, * work;

    fbt = (struct free_block_type*)malloc(sizeof(struct free_block_type));
    if (!fbt) return -1;
    fbt->size = ab->size;
    fbt->start_addr = ab->start_addr;
    /*插入到空闲区链表的头部并将空闲区按地址递增的次序排列*/
    fbt->next = free_block;
    free_block = fbt;
    rearrange(MA_FF);
    fbt = free_block;
    while (fbt != NULL) {
        work = fbt->next;
        if (work != NULL)
        {
            /*如果当前空闲区与后面的空闲区相连,则合并*/
            if (fbt->start_addr + fbt->size == work->start_addr)
            {
                fbt->size += work->size;
                fbt->next = work->next;
                free(work);
                continue;
            }
        }
        fbt = fbt->next;
    }
    rearrange(algorithm); /*重新按当前的算法排列空闲区*/
    return 1;
}


/*释放ab数据结构节点*/
int dispose(struct allocated_block* free_ab) {
    struct allocated_block* pre, * ab;

    if (free_ab == allocated_block_head) { /*如果要释放第一个节点*/
        allocated_block_head = allocated_block_head->next;
        free(free_ab);
        return 1;
    }

    pre = allocated_block_head;
    ab = allocated_block_head->next;

    while (ab != free_ab) { pre = ab;  ab = ab->next; }
    pre->next = ab->next;
    free(ab);
    return 2;
}

/* 显示当前内存的使用情况,包括空闲区的情况和已经分配的情况 */
display_mem_usage() {
    struct free_block_type* fbt = free_block;
    struct allocated_block* ab = allocated_block_head;
    if (fbt == NULL) return(-1);
    printf("----------------------------------------------------------\n");

    /* 显示空闲区 */
    printf("Free Memory:\n");
    printf("%20s %20s\n", "      start_addr", "       size");
    while (fbt != NULL) {
        printf("%20d %20d\n", fbt->start_addr, fbt->size);
        fbt = fbt->next;
    }
    /* 显示已分配区 */
    printf("\nUsed Memory:\n");
    printf("%10s %20s %10s %10s\n", "PID", "ProcessName", "start_addr", " size");
    while (ab != NULL)
    {
        printf("%10d %20s %10d %10d\n", ab->pid, ab->process_name, ab->start_addr, ab->size);
        ab = ab->next;
    }
    printf("----------------------------------------------------------\n");
    return 0;
}

/*删除进程,归还分配的存储空间,并删除描述该进程内存分配的节点*/
kill_process()
{
    struct allocated_block* ab;
    int pid;
    printf("Kill Process, pid=");
    scanf("%d", &pid);
    ab = find_process(pid);
    if (ab != NULL)
    {
        free_mem(ab); /*释放ab所表示的分配区*/
        dispose(ab);  /*释放ab数据结构节点*/
    }
}

main()
{
    char choice;
    pid = 0;
    free_block = init_free_block(mem_size); //初始化空闲区
    for (;;)
    {
        display_menu();	//显示菜单
        fflush(stdin);
        choice = getchar();	//获取用户输入
        switch (choice)
        {
        case '1':  set_mem_size();                   break;       //设置内存大小
        case '2': set_algorithm();        flag = 1;    break;	       //设置分配算法
        case '3': new_process();          flag = 1;    break;	       //创建新进程
        case '4':   kill_process();       flag = 1;    break;	       //删除进程
        case '5':   display_mem_usage();  flag = 1;    break;         //显示内存使用
        case '0':   do_exit(); exit(0);                break;	    //释放链表并退出
        default: break;
        }
    }
}

五、结果分析与总结
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
FF算法是以空闲链的首地址递增顺序组织起来,当提出分配需求时,遍历组织好的空白链,找到第一个空间大于等于分配需求的空白分配块分配。若遍历一遍都未找到满足需求的空白块,则分配失败;BF“最佳”指的是大小合适,最接近。空白链以容量大小的顺序组织,每次遍历空白链查找第一个能满足需求的空白块进行分配,这样就一定程度减少了外部碎片的大小。也避免了“大材小用”;WF最坏适应算法和最佳使用算法的空白块选择策略刚好相反,它在扫描整个空表链时,总是挑选一个最大空闲块,从中分割需求的内存块,实际上,这样的算法未必是最坏的
循环首次适应算法的排序方式和首次适应算法相同(查找的起始位置不同),在修改过程中添加一个指针来指明上次查找的位置,从而从下次查找时从此处开始。在从特定位置进行查找时,查找结束的标志有所改变,前面几种结束的表示均是到链尾,而循环首次适应算法查找结束标志是再次查找特定位置。

  • 5
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

君问归期魏有期

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值