关闭

动态存储管理

标签: 动态存储管理
303人阅读 评论(0) 收藏 举报
分类:

1.边界标识法

//BoundaryTagMethod.c
#include <stdio.h>
#include <stdlib.h>

//------------边界标识法---------------
typedef char OtherType;
typedef struct WORD{//WORD为内存字类型
    union{
        WORD *llink;//位于head区域,指向前驱结点
        WORD *uplink;//位于foot区域,指向本结点
    };
    int tag;//块标识,0为空闲,1为占用,head区域和foot区域都有
    int size;//位于head区域,标识块大小。
    WORD *rlink;//位于head区域,指向后继结点
    OtherType other;//字的其他部分
}WORD, head, foot, *Space;//*Space:可利用空间指针类型

#define FootLoc(p) p+p->size-1//指向p所指结点的底部

//data field
Space p,f;
int e;//常量e

//此函数用于分配空闲块
Space AllocBoundTag(Space pav, int n){
    //若有不小于n的空闲块,则分配相应的存储块,并返回其首地址;否则,返回NULL
    //若分配后可利用空间表不空,则pav指向表中刚分配过的结点的后继结点

    for (p = pav; p&&p->size < n&&p->rlink != pav; p = p->rlink);//向后查找不小于n的空闲块
    if (!p || p->size < n) return NULL;//找不到,返回空指针
    else{           //找到了空闲块,并由p指向
        f = FootLoc(p);//f指向结点foot区域
        pav = p->rlink;//pav指向*p结点的后继结点
        if (p->size - n <= e){//符合此条件,整块分配
            if (pav == p)//p的后继结点就是它自己,将它分配出去,再无空闲结点
                pav = NULL;
            else{//在表中删除分配的结点
                pav->llink = p->llink;
                p->llink->rlink = pav;
            }
            p->tag = f->tag = 1;//修改分配结点的头部和底部标志
        }
        else{//分配该块的后n个字
            f->tag = 1;//修改分配块的foot区域标识
            p->size -= n;//置剩余块大小为n
            f = FootLoc(p);//f指向剩余块foot区域
            f->tag = 0;//修改剩余块foot区域tag
            f->uplink = p;//修改剩余块foot区域uplink
            p = f + 1;//p指向分配块head区域
            p->tag = 1;//修改分配块head区域tag
            p->size = n;//修改分配块head区域size
        }
    return p;
    }
}

/*回收算法,共四种情况(阅读代码时参考课本图示)*/

//(1)释放块的左右邻区均为占用块
status release1(omit...){
    p->tag = 0;
    FootLoc(p)->uplink = p;
    FootLoc(p)->tag = 0;
    if (!pav)
        pav = p->llink = p->rlink = p;
    else{   //一个前插的过程
        q = pav->llink;
        p->rlink = pav;
        p->llink = q;
        q->rlink = pav->llink = p;
        pav = p;//令刚释放的结点为下次分配时最先查询的结点
    }

}

//(2)释放块的左邻区为空闲块,而右邻区为占用块
status release2(omit...){
    n = p->size;//释放块的大小
    s = (p - 1)->uplink;//左邻空闲块的头部地址
    s->size += n;//设置新的空闲块的大小
    //设置新的空闲块底部
    f = p + n - 1;
    f->uplink = s;
    f->tag = 0;
}
//(3)释放块的右邻区为空闲块,左邻区为占用块
status release3(omit...){
    t = p + p->size;//t是右邻空闲块的头部地址
    p->tag = 0;//p为合并后的结点头部地址
    q = t->llink;//q为*t结点在可利用空间表中的前驱结点的头部地址
    p->llink = q; q->rlink = p;//q指向*p的前驱
    q1 = t->rlink;//q1为*t结点在可利用空间表中的后继结点的头部地址
    p->rlink = q1; q1->llink = p;//q1指向*p的后继
    p->size += t->size;//新的空闲块的大小
    FootLoc(t)->uplink = p;//底部指针指向新结点的头部
}

//(4)释放块的左右邻区均为空闲块
status release1(omit...){
    n = p->size;//释放块的大小
    s = (p - 1)->uplink;//s指向左邻块
    t = p + p->size;//t指向右邻块
    s->size += n + t->size;//设置新结点的大小
    q = t->llink; q1 = t->rlink;
    q->rlink = q1; q1->llink = q;//删去右邻空闲表结点
    FootLoc(t)->uplink = s;//新结点底部指针指向其头部
}

2.伙伴系统

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


#define m 16    //可利用空间总容量64K字的2的幂次,子表的个数为m+1
typedef struct WORD_b{
    WORD_b *llink;//指向前驱结点
    int tag;//块标识,0代表空闲。1代表占用
    int kval;//块大小,值为2的幂次k
    WORD_b *rlink;//头部域,指向后继结点
    OtherType other;//字的其它部分
}WORD_b, head;//WORD内存字节类型。结点的第一个字是head
typedef struct HeadNode{//
    int nodesize;//该链表的空闲块的大小
    WORD_b *first;//该链表的表头指针
}FreeList[m + 1];//表头向量类型

//data field
int k,i;
WORD_b *pa,*pre,*suc;


//此函数分配空闲空间
WORD_b *AllocBuddy(FreeList avail, int n){
    //avail[0...m]为可利用空间表,n为申请分配量。
    //若有不小于n的空闲块,则分配相应的存储块,并返回其首地址;否则返回NULL

    for (k = 0; k <= m && (avail[k].nodesize < n + 1 || !avail[k].first); k++);//查找满足分配要求的子表
    if (k>m) return NULL;//分配失败,返回NULL
    else{   //进行分配
        pa = avail[k].first;//pa指向可分配子表的第一个结点
        pre = pa->llink; suc = pa->rlink;//分别指向前驱和后继
        if (pa == suc) avail[k].first = NULL;//分配后该子表变成空表
        else{//从子表中删除*p结点
            pre->rlink = suc;
            suc->llink = pre;
            avail[k].first = suc;
        }
        for (i = 1; avail[k - i].nodesize >= n + 1; i++){//将剩余块插入子表
            pi = pa + pow(2, k - 1);  pi->rlink = pi;    pi->llink = pi;
            pi->tag = 0;              pi->kval = k - i;  avail[k - 1].first = pi;
        }
        pa->tag = 1;
        pa->kval = k - (--i);
    }

    return pa;
}

3.无用单元收集

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

void MarkList(GList GL){
    //遍历非空广义表GL(GL!=NULL且GL->mark==0),对表中所有未加标志的结点加标志。
    t = NULL;//t记录当前结点的母表结点
    p = GL;//p指向当前结点
    finished = FALSE;

    while (!finished){
        while (p->mark == 0){
            p->mark = 1;
            //MarkHead(p)过程
            q = p->p.hp;//q指向*p的表头
            if (q&&q->mark == 0){
                if (q->tag == 0) q->mark = 1;//表头为原子结点
                else{//继续遍历子表
                    p->p.hp = t;
                    p->tag = 0;
                    t = p;
                    p = q;
                }
            }
        }
        q = p->p.tp;//q指向*p的表尾
        if (q&&q->mark == 0){//继续遍历表尾
            p->p.tp = t;
            t = p;
            p = q;
        }//BackTrack(finished)的细化
        else{
            while (t&&t->tag == 1){//从表尾回溯
                q = t;
                t = q->p.tp;
                q->p.tp;
                p = q;
            }
            if (!t) finished = TRUE;//结束
            else{//从表头回溯
                q = t;
                t = q->p.hp;
                q->p.hp = p;
                p = q;
                p->tag = 1;
            }
        }
    }
}

1
0
查看评论

动态存储管理

动态存储管理为什么需要动态存储管理程序中需要用变量(各种简单类型变量、数组变量等)保存被处理的数据和各种状态信息,变量在使用之前必须安排好存储:放在哪里、占据多少存储单元,等等,这个工作被称作存储分配。用机器语言写程序时,所有存储分配问题都需要人处理,这个工作琐碎繁杂、很容易出错。在用高级语言写程序...
  • tommy_lgj
  • tommy_lgj
  • 2006-08-23 11:52
  • 2731

数据结构随笔—动态存储管理

动态存储管理的基本问题是如何应用户请求分配内存,如何回收那些用户不在使用而释放的内存。 经过一段时间的运行,有些用户运行结束,它所占用的内存区变成空闲块,只就使整个内存区呈现出占用快和空闲块交错的状态,假如此时又有新的用户进入系统请求分配内存,这时通常有两种做法: (1)、继续从高地址的空闲块中...
  • u011656203
  • u011656203
  • 2015-04-10 16:12
  • 1186

【操作系统笔记】动态存储管理

操作系统中常用来管理内存的动态分配和回收的方法有边界标识法和伙伴系统。 系统将所有的空闲块链接在一个双重循环链表结构的可利用空间表中。系统的特点在于:在每个内存区的头部和底部两个边界上分别设有标识,以标识该区域是占用块或空闲块,使得在回收用户释放的空闲块时易于判别在物理位置上与其相邻的内存...
  • mmc_maodun
  • mmc_maodun
  • 2014-03-08 08:40
  • 2974

第八章 动态存储管理

8.11 typedef struct {                     char *start;&...
  • Beta3
  • Beta3
  • 2007-06-13 21:46
  • 421

3.动态存储管理和程序调试

point.h ---------------------------------------------------------------------------- #include #include using namespace std; class point{ pri...
  • u010392719
  • u010392719
  • 2013-05-03 17:53
  • 343

C语言 动态存储管理

为什么需要动态存储管理 程序中需要用变量(各种简单类型变量、数组变量等)保存被处理的数据和各种状态信息,变量在使用之前必须安排好存储:放在哪里、占据多少存储单元,等等,这个工作被称作存储分配。用机器语言写程序时,所有存储分配问题都需要人处理,这个工作琐碎繁杂、很容易出错。在用高级语言写程序时,人通常...
  • zm_god
  • zm_god
  • 2009-06-03 21:38
  • 646

动态存储管理之一【严蔚敏】

用户请求系统分配内存:(两种策略) 1)系统继续从高地址的空闲块中进行分配,不理会已分配的内存区是否已经空闲,直到无法满足分配请求时,系统再去回收用户不再使用的空闲块。 2)用户执行完结束,立马分配过的空闲块释放,用户请求分配时,遍历整个内存区,找合适空闲块分配。 可利用空间表实现内存分配方法: 表...
  • MooMLu
  • MooMLu
  • 2017-04-26 18:52
  • 188

数据结构之动态存储管理(C语言)

一、 概述1. 占用块占用块:已分配给用户使用的地址连续的内存区 可利用空间块:未曾分配的地址连续的内存区 2. 动态存储分配过程的内存状态系统运行一段时间后,有些程序的内存被释放,造成了上图(b)中的状态。假如此时又有新的程序请求分配内存,系统将如何做呢?通常有两种做法:一种策略是继续从高地址的...
  • kang___xi
  • kang___xi
  • 2017-09-05 10:43
  • 71

数据结构复习笔记七:动态存储管理

一、动态存储管理 1、动态存储管理的基本问题是系统如何应用户提出的请求分配内存?又如何回收那些用户不再使用而释放的内存,以 备新的请求产生时重新分配 2、占用块:使用连续的内存地址区 3、可利用空间块或空闲块:未曾被分配的地址连续的内存 4、分配内存空间的两种策略 5、可利用空间表:目录表、链表 ...
  • chenkeng2009081030
  • chenkeng2009081030
  • 2014-03-03 21:54
  • 673

数据结构伪C代码:8.动态存储管理

//可利用空间表的结点结构定义 typedef struct WORD{ //WORD:内存字类型 union{ //head和foot分别是结点的第一个字和最后的字 WORD *llink; //头部域,指向前...
  • fanpengfei0
  • fanpengfei0
  • 2014-07-21 16:21
  • 534
    个人资料
    • 访问:193804次
    • 积分:4834
    • 等级:
    • 排名:第7046名
    • 原创:290篇
    • 转载:39篇
    • 译文:0篇
    • 评论:9条
    最新评论