操作系统实验二——内存平均利用率与分配策略的研究

原创 2006年05月22日 12:10:00

    参考windows任务管理器中内存占用的情况,在256M的总内存中,各个进程所占的内存从几十K到几十M不等,基本可以看成是均匀分布。即,每个进程申请使用的内存占总内存的百分比比较接近实际的数据为从千分之几到百分之十几,在这里,我们取从0.02%15%

    但是为了说明情况,在实验中,我将申请内存占总内存的比率分为六个区间,分别为:0.02%——2%0.02%——8%0.02%——15%0.02%——25%0.02%——40%0.02%——60%。对于四种不同的分配策略,分别考察从区间0.02%——2%变化到0.02%——60%时内存平均利用率的变化情况。可以得出较一般的结论。

实验结果如下:

将实验结果用图示的方法表现出来如下图所示:

    从这张内存分配策略实验比较图可以看出,总体来说,仅就内存平均利用率这一个指标来看,best-fit > first-fit > next-fit > worst-fit。且随着申请内存占总内存比率的增大,各种分配策略的内存平均利用率趋于一致。从各种分配策略单独来看,随着申请内存占总内存比率的增大,各种分配策略的内存平均利用率都有所下降,但下降的速率有所差别。相比较而言,平均利用率最大的best-fit下降的幅度最大,而平均利用率最小的worst-fit下降的幅度最小,first-fitnext-fit居于它们之间。

    总体结论:内存平均利用率的好坏不仅和内存的分配策略有关,还和进程申请内存占总内存的平均比率有关。在同等条件下,若仅考虑内存分配策略,则best-fit > first-fit > next-fit > worst-fit,若仅考虑申请内存占总内存的比率,则随着申请内存占总内存比率的增大,内存平均使用率下降,下降的斜率best-fit > first-fit > next-fit > worst-fit

附:

对程序的一点说明:

程序中,用两个数据结构来维护内存使用状况,分别是USED_LINKFREE_LINK。链表中的每一项都是一个BLOCK_NODE,其定义为:

typedef struct block{
 //int blockId;
 int startPosition;
 int endPosition;
 int length;
 struct block *next;
} BLOCK_NODE, *pBLOCK_NODE;

程序中,模拟内存的大小为256M,即

#define MEM_SIZE 268435456 //256M

内存初始化,申请内存以及释放内存的函数分别定义为:

void mem_init();

int mem_request(int size, STRATEGY strategy);

bool mem_release(int startPosition);

其中,STRATEGY对应于四种不同的分配策略:

typedef enum {FIRST_FIT, NEXT_FIT, BEST_FIT, WORST_FIT} STRATEGY;

完整的源代码如下:

mem.h

#ifndef _MEM_H
#define _MEM_H

#include <stdio.h>

//#define MEM_SIZE 1024   //1K
//#define MEM_SIZE 1048576  //1M
#define MEM_SIZE 268435456 //256M

typedef struct block{
 //int blockId;
 int startPosition;
 int endPosition;
 int length;
 struct block *next;
} BLOCK_NODE, *pBLOCK_NODE;

typedef struct {
 pBLOCK_NODE head;
 pBLOCK_NODE tail;
 int blockNum;
}USED_LINK, FREE_LINK;

typedef enum {FIRST_FIT, NEXT_FIT, BEST_FIT, WORST_FIT} STRATEGY;

void mem_init();
int mem_request(int size, STRATEGY strategy);
bool mem_release(int startPosition);

#endif

 

mem.cpp

#include <stdio.h>
#include <memory.h>
#include "mem.h"

USED_LINK used_link;
FREE_LINK free_link;

pBLOCK_NODE fromThis = free_link.head;
//char memory[MEM_SIZE];

//内存初始化。
void mem_init() {
 //memset(memory, 0, MEM_SIZE);

 //使用链表置空。
 used_link.head = NULL;
 used_link.tail = NULL;
 used_link.blockNum = 0;

 //空闲连标初始为一个完整的空闲块,块大小为整个内存区。
 pBLOCK_NODE tmp = new BLOCK_NODE;
 tmp->startPosition = 0;
 tmp->endPosition = MEM_SIZE - 1;
 tmp->length = MEM_SIZE;
 tmp->next = NULL;

 free_link.head = tmp;
 free_link.tail = tmp;
 free_link.blockNum = 1;
}

//内存请求,按一定的分配策略分配,
//并返回分配后内存的首地址。
int mem_request(int size, STRATEGY strategy) {
 //若size小于等于零或者大于总内存大小,则错误返回。
 if (size <= 0 || size > MEM_SIZE) {
  //printf("Memory size error!/n");
  return -1;
 }

 pBLOCK_NODE temp = NULL;

 //first_fit
 //搜索能够满足请求的内存块。
 //若没有满足要求的内存块,则返回-1。
 if (strategy == FIRST_FIT) {
  temp = free_link.head;
  while (free_link.blockNum > 0) {
   if (temp == NULL) {
    break;
   } else if (temp->length >= size) {
    break;
   } else {
    temp = temp->next;
   }
  }
 }

 //next_fit strategy
 if (strategy == NEXT_FIT) {
  int blockNum = free_link.blockNum;
  for (int i = 0; i < blockNum; i++) {
   if (fromThis == NULL) {
    fromThis = free_link.head;
   }
   if (fromThis->length >= size) {
    temp = fromThis;
    fromThis = fromThis->next;
    break;
   } else {
    fromThis = fromThis->next;
   }
  }
 }

 //best_fit
 if (strategy == BEST_FIT) {
  int t = MEM_SIZE + 1;
  pBLOCK_NODE tp = free_link.head;
  while (free_link.blockNum > 0) {
   if (tp == NULL) {
    break;
   } else if (tp->length >= size) {
    if (tp->length < t) {
     temp = tp;
     t = tp->length;
    }
    tp = tp->next;
   } else {
    tp = tp->next;
   }
  }
 }

 //worst_fit strategy
 if (strategy == WORST_FIT) {
  int t = 0;
  pBLOCK_NODE tp = free_link.head;
  while (free_link.blockNum > 0) {
   if (tp == NULL) {
    break;
   } else if (tp->length >= size) {
    if (tp->length > t) {
     temp = tp;
     t = tp->length;
    }
    tp = tp->next;
   } else {
    tp = tp->next;
   }
  }
 }

 if (temp == NULL) {
  //printf("Alloc Failed!/n");
  return -1;
 } else {
  //若存在满足要求的内存块,则创建新的内存块。
  pBLOCK_NODE newNode = new BLOCK_NODE;
  newNode->startPosition = temp->startPosition;
  newNode->endPosition = newNode->startPosition + size - 1;
  newNode->length = size;
  newNode->next = NULL;

  //将新分配的内存块信息插入到使用链表中。
  if (used_link.blockNum == 0) {
   used_link.head = newNode;
   used_link.tail = newNode;
   used_link.blockNum = 1;
  } else if (used_link.blockNum >= 1) {
   //按内存块首地址递增的方式插入。
   pBLOCK_NODE preNode = NULL;
   pBLOCK_NODE curNode = used_link.head;
   if (newNode->startPosition < curNode->startPosition) {
    newNode->next = used_link.head;
    used_link.head = newNode;
    used_link.blockNum++;
   } else {
    while (curNode->startPosition < newNode->startPosition) {
     preNode = curNode;
     curNode = curNode->next;
     if (curNode == NULL) {
      break;
     }
    }
    if (curNode == NULL) {
     used_link.tail->next = newNode;
     used_link.tail = newNode;
     used_link.blockNum++;
    } else {
     newNode->next = curNode;
     preNode->next = newNode;
     used_link.blockNum++;
    }
   }
  }

  //修改空闲链表中可用内存块的信息。
  if (temp->length == size) {
   if (temp == free_link.head) {
    free_link.head = temp->next;
    if (free_link.head == NULL) {
     free_link.tail = NULL;
    }

    delete temp;
    free_link.blockNum--;
   } else {
    pBLOCK_NODE preNode = free_link.head;
    pBLOCK_NODE curNode = free_link.head->next;
    while (temp != curNode) {
     preNode = curNode;
     curNode = curNode->next;
    }
    if (curNode == free_link.tail) {
     free_link.tail = preNode;
     preNode->next = NULL;
    } else {
     preNode->next = curNode->next;
    }

    delete temp;
    free_link.blockNum--;
   }
  } else if (temp->length > size) {
   temp->startPosition += size;
   temp->length -= size;
  }

  //返回分配成功后的首地址。
  return newNode->startPosition;
 }
}

bool mem_release(int startPosition) {
 pBLOCK_NODE release_target = used_link.head;
 pBLOCK_NODE preNode = NULL;

 //此时使用链表为空。
 if (release_target == NULL) {
  printf("No such alloced memory!/n");
  return false;
 }
 //搜索需要释放的内存块。
 while (release_target->startPosition != startPosition) {
  preNode = release_target;
  release_target = release_target->next;
  if (release_target == NULL) {
   break;
  }
 }

 //修改使用链表中内存使用信息。删除释放内存的信息结点。
 if (release_target == NULL) {
  printf("No such alloced memory!/n");
  return false;
 } else if (release_target == used_link.head && release_target == used_link.tail) {
  used_link.head = NULL;
  used_link.tail = NULL;
  used_link.blockNum--;
 } else if (release_target == used_link.head) {
  used_link.head = used_link.head->next;
  used_link.blockNum--;
 } else if (release_target == used_link.tail) {
  preNode->next = release_target->next;
  used_link.tail = preNode;
  used_link.blockNum--;
 } else {
  preNode->next = release_target->next;
  used_link.blockNum--;
 }

 //修改空闲链表信息,将释放后可重新使用的内存块信息写入空闲链表,
 //并进行必要的合并。
 pBLOCK_NODE insertBefore = free_link.head;
 preNode = NULL;
 if (free_link.head == NULL) {
  free_link.head = release_target;
  free_link.tail = release_target;
  release_target->next = NULL;
  free_link.blockNum++;
 } else if (release_target->startPosition < free_link.head->startPosition) {
  if (release_target->endPosition + 1 == free_link.head->startPosition) {
   free_link.head->startPosition = release_target->startPosition;
   free_link.head->length += release_target->length;
   delete release_target;
  } else {
   release_target->next = free_link.head;
   free_link.head = release_target;
   free_link.blockNum++;
  }
 } else {
  while (insertBefore->startPosition < release_target->startPosition) {
   preNode = insertBefore;
   insertBefore = insertBefore->next;
   if (insertBefore == NULL) {
    break;
   }
  }
  if (insertBefore == NULL) {
   if (release_target->startPosition - 1 == preNode->endPosition) {
    preNode->endPosition = release_target->endPosition;
    preNode->length += release_target->length;
    delete release_target;
   } else {
    preNode->next = release_target;
    free_link.tail = release_target;
    release_target->next = NULL;
    free_link.blockNum++;
   }
  } else {
   if (release_target->startPosition - 1 == preNode->endPosition
    && release_target->endPosition + 1 == insertBefore->startPosition) {
    if (insertBefore == free_link.tail) {
     preNode->endPosition = insertBefore->endPosition;
     preNode->length += (release_target->length + insertBefore->length);
     preNode->next = insertBefore->next;

     if (fromThis == insertBefore) {
      fromThis = preNode;
     }

     delete insertBefore;
     delete release_target;
     free_link.tail = preNode;
     free_link.blockNum--;
    } else {
     preNode->endPosition = insertBefore->endPosition;
     preNode->length += (release_target->length + insertBefore->length);
     preNode->next = insertBefore->next;

     if (fromThis == insertBefore) {
      fromThis = preNode;
     }

     delete insertBefore;
     delete release_target;
     free_link.blockNum--;
    }
   } else if (release_target->startPosition - 1 == preNode->endPosition) {
    preNode->endPosition = release_target->endPosition;
    preNode->length += release_target->length;
    delete release_target;
   } else if (release_target->endPosition + 1 == insertBefore->startPosition) {
    insertBefore->startPosition = release_target->startPosition;
    insertBefore->length += release_target->length;
    delete release_target;
   } else {
    release_target->next = preNode->next;
    preNode->next = release_target;
    free_link.blockNum++;
   }
  }
 }

 return true;
}

 

allocate.cpp

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include "mem.h"

#define ROUNDS 1000000
extern FREE_LINK free_link;
extern USED_LINK used_link;

int computeSize(double rangeLow, double rangeHigh);
double computeFraction(STRATEGY strategy, double rangeLow, double rangeHigh);
double averageRand(double min, double max);
void computeAndPrint(double rangeLow, double rangeHigh);

main() {
 mem_init();
 srand((unsigned)time(NULL));

 printf("申请内存占总内存比率为0.02%%--2%%时:/n");
 computeAndPrint(0.0002, 0.02);
 printf("/n申请内存占总内存比率为0.02%%--8%%时:/n");
 computeAndPrint(0.0002, 0.08);
 printf("/n申请内存占总内存比率为0.02%%--15%%时:/n");
 computeAndPrint(0.0002, 0.15);
 printf("/n申请内存占总内存比率为0.02%%--25%%时:/n");
 computeAndPrint(0.0002, 0.25);
 printf("/n申请内存占总内存比率为0.02%%--40%%时:/n");
 computeAndPrint(0.0002, 0.40);
 printf("/n申请内存占总内存比率为0.02%%--60%%时:/n");
 computeAndPrint(0.0002, 0.60);

 return 0;
}

void computeAndPrint(double rangeLow, double rangeHigh) {
 printf("first_fit内存平均利用率:/t%f/n", computeFraction(FIRST_FIT, rangeLow, rangeHigh));
 printf("next_fit内存平均利用率:/t%f/n", computeFraction(NEXT_FIT, rangeLow, rangeHigh));
 printf("best_fit内存平均利用率:/t%f/n", computeFraction(BEST_FIT, rangeLow, rangeHigh));
 printf("worst_fit内存平均利用率:/t%f/n", computeFraction(WORST_FIT, rangeLow, rangeHigh));
}

double computeFraction(STRATEGY strategy, double rangeLow, double rangeHigh) {
 int pointerTemp = -1;
 double fraction = 0;
 for (int i = 0; i < ROUNDS; i++) {
  int requestSize = 0;
  do {
   requestSize = computeSize(rangeLow, rangeHigh);
   pointerTemp = mem_request(requestSize, strategy);
  } while (pointerTemp != -1);

  int temp = 0;
  pBLOCK_NODE nodeTemp = free_link.head;
  while (nodeTemp != NULL) {
   temp += nodeTemp->length;
   nodeTemp = nodeTemp->next;
  }
  fraction += (MEM_SIZE - (double)temp)/MEM_SIZE;

  if (used_link.blockNum != 0) {
   int releaseBlock = rand() % used_link.blockNum;
   nodeTemp = used_link.head;
   for (int j = 0; j < releaseBlock; j++) {
    nodeTemp = nodeTemp->next;
   }
   mem_release(nodeTemp->startPosition);
  }
 }
 fraction /= ROUNDS;

 //printf("Average used fraction: %f/n", fraction);
 return fraction;
}

int computeSize(double rangeLow, double rangeHigh) {
 return (int)(averageRand(rangeLow, rangeHigh)*MEM_SIZE);
}

double averageRand(double min, double max) {
 int minInteger = (int)(min*10000);
 int maxInteger = (int)(max*10000);
 int diffInteger = maxInteger - minInteger;
 double randInteger = (double)rand()/RAND_MAX;
 int resultInteger = (int) ( randInteger * diffInteger + minInteger );

 return resultInteger/10000.0;
}

各种内存分配方式产生的动机

题干中的连续分配,应该是包括单一连续分配 和分区分配 两种分配策略。单一连续分配简单,适用于单用户、单任务的操作系统。 为了支持多道程序运行,引入了分区式内存分配,其又分为固定分区和动态分区,主要...
  • hyqsong
  • hyqsong
  • 2016年05月17日 14:26
  • 356

常见内存分配算法及优缺点

常见内存分配算法及优缺点如下:   (1)首次适应算法。使用该算法进行内存分配时,从空闲分区链首开始查找,直至找到一个能满足其大小需求的空闲分区为止。然后再按照作业的大小,从该分区中划出一块内存分配...
  • xuwanlong111
  • xuwanlong111
  • 2014年09月16日 10:15
  • 3039

操作系统原理:动态内存分配

用户层malloc的实现malloc的底层调用sbrk和mmapmalloc是C语言标准库函数,是在用户层实现的。在Linux里,malloc编译好,是在run-time的动态库so中,通过标准库头文...
  • thisinnocence
  • thisinnocence
  • 2017年04月12日 23:21
  • 1340

动态分区分配内存管理源代码(附有实验报告)最佳适应算法(Best Fit)循环首次适应算法(Next Fit)

  • 2015年05月24日 20:27
  • 165KB
  • 下载

计算cpu利用率和内存利用率

Linux 下CPU、内存利用率--计算(二) 当需要频繁地获取,可以选择这种方法。 1、原理 (1)   CPU利用率 在Linux下,CPU利用率分为用户态,系统态和空闲态...
  • htjx99
  • htjx99
  • 2015年01月20日 17:08
  • 1889

内存分区分配算法

在多道程序的存储管理模式中,分区分配算法显得尤为重要。这里主要说一下动态分区分配算法。 主要有下面五种分配算法: 首次适应算法 循环首次适应算法 最佳适应算法 最坏适应算法 快速适应算法 对于这几种...
  • zhuxinquan61
  • zhuxinquan61
  • 2016年04月21日 22:15
  • 2218

Android性能优化之内存

原文出处:http://blog.csdn.net/qq_23191031。作者: 大圣代 APP内存的使用,是评价一款应用性能高低的一个重要指标。虽然现在智能手机的内存越来越大,但是一个好...
  • ZhaiKun68
  • ZhaiKun68
  • 2017年07月25日 13:35
  • 239

内存管理中一些算法

在内存管理中存在这两类算法:一类是内存分配算法,一类是页面置换算法 内存分配算法:是指怎么从连续的逻辑地址空间上分配内存地址给进程。常见内存分配算法及优缺点如下:  (1)首次适应算法。使用该算法进行...
  • suwei19870312
  • suwei19870312
  • 2010年09月23日 17:38
  • 6185

内存连续分配方式采用的几种算法及各自优劣。

连续分配方式,是指为一个用户程序分配一个连续的内存空间。它主要包括单一连续分配、固定分区分配和动态分区分配。 单一连续分配 内存在此方式下分为系统区和用户区,系统区仅提供给操作系统使用,通...
  • qq_33774935
  • qq_33774935
  • 2016年10月01日 18:24
  • 604

计算cpu利用率和内存利用率

Linux 下CPU、内存利用率--计算(二) 当需要频繁地获取,可以选择这种方法。 1、原理 (1)   CPU利用率 在Linux下,CPU利用率分为用户态,系统态和空闲态...
  • htjx99
  • htjx99
  • 2015年01月20日 17:08
  • 1889
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:操作系统实验二——内存平均利用率与分配策略的研究
举报原因:
原因补充:

(最多只允许输入30个字)