伙伴算法

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

#define MIN_MOMORY_SIZE 536870912   //随机产生的最小内存空间:512M (最大为1G)   
#define INDEX_SIZE 30               //哈希索引表大小   
#define WORKTIME 1500               //系统工作时间   
#define MAX_REQ_SIZE 268435456      //申请空闲内存分配的最大容量:256M   
#define MIN_DUE 30                  //使用内存块的最短时间  
#define MAX_DUE 90                  //使用内存块的最长时间  
#define OCCUPY_INTERVAL 60          //每次分配的最大间隔   
#define USED 1                      //内存块被使用   
#define UNUSED 0                    //内存块未被使用  

//内存块链表结点结构   
typedef struct buddy_node {  
    int flag;                       //标记空间是否被使用  
    int base;                       //本块儿内存的基地址   
    int occupy;                     //实际使用空间大小   
    int fragment;                   //碎片大小   
    int duetime;                    //使用时间  
    struct buddy_node *nextPtr;     //指向下一个结点   
} Buddy, *BuddyPtr;  

//哈希索引表结构   
typedef struct hash_table {  
    int nodesize;  
    BuddyPtr headPtr;  
} IndexTable;  

IndexTable table[INDEX_SIZE];//使用哈希表管理伙伴系统   
int ready = 0;               //需要分配内存的时刻   
int availSpace;              //可分配空间大小   
int totalFragment = 0;       //总碎片大小   

//函数:根据k的值计算哈希表项链接的内存块的大小  
int get_size (int k)  
{  
    int i, nodesize = 1;  

    for (i = 0; i < k; i ++)  
        nodesize *= 2;  

    return nodesize;  
}  

//函数:初始化哈希索引表   
void ini_index (void)  
{  
    int i;  

    for (i = 0; i < INDEX_SIZE; i ++) {  
        table[i].nodesize = get_size(i);  
        table[i].headPtr = NULL;  
    }   
}  

//函数:初始化伙伴系统  
void int_system (int memory_size)  
{  
    int i, addr = 0;  
    int left = memory_size;  
    BuddyPtr newnodePtr = NULL;  

    //初始化可分配空间大小和碎片大小   
    availSpace = memory_size;   
    totalFragment = 0;  

    //将内存分割成尽量大的2倍数的空闲块并插入到相应的索引表项中  
    for (i = INDEX_SIZE-1; left > 0; i --) {  
        if (left / table[i].nodesize == 1) {  
            newnodePtr = (BuddyPtr) malloc (sizeof (Buddy));//分配结点   
            newnodePtr->flag = UNUSED;  
            newnodePtr->base = addr;  
            newnodePtr->occupy = 0;   
            newnodePtr->fragment = 0;  
            newnodePtr->duetime = 0;  
            newnodePtr->nextPtr = NULL;  
            table[i].headPtr = newnodePtr;  
            addr += table[i].nodesize;  
            left -= table[i].nodesize;  
        }  
    }   
}  

//函数:程序运行结束后释放所有结点  
void free_system (void)  
{  
    int i;  
    BuddyPtr tempPtr = NULL, tofreePtr = NULL;  

    for (i = 0; i < INDEX_SIZE; i ++) {  
        if (table[i].headPtr) {  
            tempPtr = table[i].headPtr;  
            table[i].headPtr = NULL;  
            //依次释放所有结点  
            while (tempPtr) {  
                tofreePtr = tempPtr;  
                tempPtr = tempPtr->nextPtr;  
                free (tofreePtr);  
            }  
        }  
    }  
}  

//函数:添加结点(形参为内存块结点的信息)   
void insert_node (int i, int inbase, int f, int occ, int frag, int d)  
{  
    BuddyPtr newnodePtr = NULL, prePtr = NULL, curPtr = NULL;  

    newnodePtr = (BuddyPtr) malloc (sizeof (Buddy));//分配结点  
    newnodePtr->base = inbase;  
    newnodePtr->flag = f;  
    newnodePtr->occupy = occ;   
    newnodePtr->fragment = frag;  
    newnodePtr->duetime = d;  
    newnodePtr->nextPtr = NULL;   
    if (table[i].headPtr == NULL)  
        table[i].headPtr = newnodePtr;  
    else {  
        curPtr = table[i].headPtr;  
        prePtr = NULL;  
        //按地址顺序插入内存块   
        while (curPtr && curPtr->base < inbase) {  
            prePtr = curPtr;  
            curPtr = curPtr->nextPtr;    
        }  
        if (prePtr == NULL) {          //插在最前   
            newnodePtr->nextPtr = curPtr;  
            table[i].headPtr = newnodePtr;  
        }  
        else if (curPtr == NULL) {     //插在最后   
            prePtr->nextPtr = newnodePtr;  
        }  
        else {                         //插在中间   
            prePtr->nextPtr = newnodePtr;  
            newnodePtr->nextPtr = curPtr;  
        }   
    }  
}  

//函数:删除结点  
int delete_node (int i, BuddyPtr delPtr)  
{  
    BuddyPtr prePtr = NULL, curPtr = NULL;  
    int basehold = delPtr->base;  

    curPtr = table[i].headPtr;  
    while (curPtr != delPtr) {  //寻找要删除的结点的位置   
        prePtr = curPtr;  
        curPtr = curPtr->nextPtr;    
    }  
    if (prePtr == NULL)         //要删除的结点在最前   
        table[i].headPtr = curPtr->nextPtr;  
    else                        //要删除的结点不在链表的最前   
        prePtr->nextPtr = curPtr->nextPtr;  

    free (curPtr);              //释放结点   

    return basehold;            //返回删除的内存块结点的基地址   
}   

//函数:伙伴系统的分配算法   
void buddy_allocate (int time_slice)  
{  
    int i, j, size, due;  
    int state = 0;              //分配状态:0为未分配,1为已分配   
    int inbase, basehold;  
    BuddyPtr curPtr = NULL;  

    if (ready == time_slice) {  //到达分配内存的时刻   
        printf ("Time %d:", time_slice);  
        size = 1 + rand () % MAX_REQ_SIZE;            //申请使用内存的大小   
        due = MIN_DUE + rand ()%(MAX_DUE - MIN_DUE);  //申请使用内存的时间  

        if (availSpace > size) {//在可分配空间大于申请空间时分配  
            //依次寻找可分配的内存块   
            for (i = 0; (i < INDEX_SIZE) && (state == 0); i ++) {  
                //找到一个不小于申请大小的块索引  
                if (table[i].nodesize >= size && table[i].headPtr) {  
                    curPtr = table[i].headPtr;  
                    //遍历相应的循环链表中   
                    while (curPtr && (state == 0)) {  
                        //找到空闲块  
                        if (curPtr->flag == UNUSED) {  
                            //空闲块的大小小于申请大小的2倍,分配   
                            if (table[i].nodesize / size == 1) {  
                                //在分配的内存块上设置信息   
                                curPtr->flag = USED;  
                                curPtr->occupy = size;  
                                curPtr->fragment = table[i].nodesize - size;  
                                curPtr->duetime = due + ready;  
                                //修改可系统分配空间和碎片大小   
                                availSpace -= table[i].nodesize;  
                                totalFragment += curPtr->fragment;  
                                state = 1;//标记已分配   
                                break;  
                            }  
                            //空闲块的大小刚大于申请大小的2倍  
                            else {  
                                basehold = delete_node (i, curPtr);//删除较大的空闲块并保留其基地址   
                                inbase = basehold + table[i].nodesize;  
                                j = i;  
                                //分割空闲块   
                                do {  
                                    j --;  
                                    inbase -= table[j].nodesize;   //设置要添加内存块结点的基地址   
                                    insert_node (j, inbase, UNUSED, 0, 0, 0);//添加较小的空闲块   
                                    printf ("A block cut takes place\n");  
                                } while (table[j].nodesize / size > 1);  
                                //分配   
                                insert_node (j, basehold, USED, size, table[j].nodesize - size, due + ready);  
                                //修改可系统分配空间和碎片大小   
                                availSpace -= table[j].nodesize;  
                                totalFragment += table[j].nodesize - size;  
                                state = 1;//标记已分配   
                            }  
                        }  
                        //块被占用,查看下一结点   
                        else  
                            curPtr = curPtr->nextPtr;  
                    }  
                }              
            }  
            printf ("Allocated %d,Fragment %d,Due %d\n", size, totalFragment, ready+due);  
        }  

        else if ((availSpace < size) && ((availSpace + totalFragment) >= size))  
            printf ("Allocation failed because of fragment!\n");  
        else  
            printf ("Allocation failed because of no enough unused space!\n");  

        ready += (1 + rand() % OCCUPY_INTERVAL);  //下次需要分配内存的时刻  
    }  
}  

//函数:伙伴系统的回收算法  
void buddy_retrieve (int time_slice)  
{  
    int i, basehold, dif;  
    int f = 0;  
    int Modnext=0;  
    BuddyPtr curPtr = NULL, todelPtr = NULL;   

    //依次查找,并回收需要回收的块   
    for (i = 0; i < INDEX_SIZE; i ++) {  
        if (table[i].headPtr) {  
            curPtr = table[i].headPtr;  
            while (curPtr) {  
                if ((curPtr->flag == USED) && (curPtr->duetime == time_slice)) {//需要回收   
                    //修改可系统分配空间和碎片大小   
                    availSpace += table[i].nodesize;  
                    totalFragment -= curPtr->fragment;  
                    //回收为空闲块   
                    curPtr->flag = UNUSED;  
                    curPtr->occupy = 0;   
                    curPtr->fragment = 0;  
                    curPtr->duetime = 0;  
                    printf ("Time %d:Retrieve %d,Fragment %d\n", time_slice, table[i].nodesize, totalFragment);  
                }  
                curPtr = curPtr->nextPtr;  
            }  
        }  
    }  

    //合并空闲块  
    for (i = 0; i < INDEX_SIZE; i ++) {  
        if (table[i].headPtr) {              
            curPtr = table[i].headPtr;  
            while (curPtr && curPtr->nextPtr) {  
                //将地址连续且都为空闲的块合并后加入下一级的链表中   
                if (curPtr->flag == UNUSED && (curPtr->nextPtr)->flag == UNUSED) {  
                    dif = (curPtr->nextPtr)->base - curPtr->base;  
                    Modnext = ((int)(curPtr->nextPtr->base))%(2*table[i].nodesize);  
                    if ((dif == table[i].nodesize)&&(Modnext==0)) {  
                        //删除两个结点   
                        todelPtr = curPtr;  
                        curPtr = curPtr->nextPtr;  
                        basehold = delete_node (i, todelPtr);  
                        todelPtr = curPtr;  
                        curPtr = curPtr->nextPtr;  
                        delete_node (i, todelPtr);  
                        insert_node (i+1, basehold, UNUSED, 0, 0, 0);//添加合并后的结点   
                        printf ("Two blocks merge\n");  
                    }  
                    else  
                        curPtr = curPtr->nextPtr;  
                }  
                else  
                    curPtr = curPtr->nextPtr;  
            }  
        }  
    }  
}  

//函数:伙伴系统的处理过程   
void buddy_system (void)  
{  
    int time_slice = 0;  

    //在每个时间片内使用分配算法和回收算法   
    for (; time_slice < WORKTIME; time_slice ++) {  
        buddy_allocate (time_slice);         //分配算法   
        buddy_retrieve (time_slice);         //回收算法   
    }  
}  


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

    ini_index ();               //初始化哈希索引表   
    srand (time (NULL));        //设置随机数种子  
    //随机产生需要管理的内存大小:512M ~ 1G   
    memory_size = MIN_MOMORY_SIZE + rand() % MIN_MOMORY_SIZE;   
    printf ("The size of memory is:%d\n", memory_size);  

    int_system (memory_size);   //初始化伙伴系统   

    buddy_system ();            //伙伴系统的处理过程  
    printf ("Time %d:System execution stops and the spaces are all freed.\n", WORKTIME);  

    free_system ();             //释放所有结点   

    return 0;  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值