residence

reside 居住

residence 宿舍

转载于:https://www.cnblogs.com/liyongguo/p/7060862.html

设计步骤 2.3.1 数据结构分析 为了实现存储资源的分配和回收,操作系统需要记录内存资源使用情况,即哪些区域尚未分配,哪些区域已经分配以及分配给哪些进程等。为此一般需要两个表,一个为分配表, 另外一个为空闲区域表。前者记录已经分配的区域, 后者记录着所有当前未被进程占用的空闲区域, 如图2-1所示。 显然, 没有记录于表中的区域即为已被进程所占用的非空闲区域,在实际的操作系统中,这些区域登记在进程的PCB中。而PCB中除了关于内存资源的信息外,还有其它大量信息。 由于本设计是对存储管理算法的模拟,所以用一个线程来代表一个进程,用线程驻留区域表来描述线程占用的内存空间,如图2-2所示。 线程名称 驻留区始址 驻留区大小 a 0 10 b 20 20 …… …… …… 图2-2 线程驻留区表 同时,需要一张表来记录各个线程对内存的请求信息,如图2-3所示。 线程名称 请求大小(KB) 预计驻留时间( 秒) thread_1 20 4 thread_2 10 5 …… …… …… 图2-3 内存申请表 2.3.2 算法分析 分配时取满足申请要求且长度最小的空闲区域。在实现时, 可将系统中所有的空闲区域按照长度由小到大的次序依次记录于空闲区域表中。与最先适应算法相类似, 当进程申请存储空间时, 系统由表的头部开始查找, 取第一个满足要求的表目。如果该表目所对应的区域长度恰好与所申请的区域长度相同, 则将该区域全部分配给申请者。否则将该区域分割为两部分, 一部分的长度与所申请的长度相同, 将其分配给申请者;另一部分即剩余部分的长度为原长度与分配长度之差, 由于剩余部分的长度已经改变,所以应重新将其按长度从小到大的顺序插入到空闲区域表中。 回收时,不仅要按回收区的首地址查询空闲区表,找到与回收区相临的空闲区,将其合并到相临区中,而且要把合并后的回收区按照长度递增的顺序插入到空闲区域表的适当位置。 2.3.3 设计并分析测试数据 假设初始内存布局如图2-4,图中的起始地址以及大小都以KB来衡量。 起始地址 0 10 20 40 70 80 85 145 160 180 占用者 a b c d e 大 小 10 10 20 30 10 5 60 15 20 20 图2-4初始内存布局 由图2-4可见,初始时共有五个线程驻留在内存,它们是a,b,c,d,e,线程驻留区表如图2-5;还有五个空闲区,空闲区域表如图2-6。 假设现在有三个线程提出内存申请,申请情况见图2-7。经过分析我们得到在每种分配算法下这三个线程所申请到的内存情况。图2-8是最佳适应算法分配情况。 2.3.4 程序设计 程序包含两个文件,一个是头文件variable_partition.h,另一个是源程序文件variable_partition.cpp。在头文件中定义了宏、数据结构、全局变量、函数声明,源程序中含有各个函数的实现。 在头文件中,结构体FREEAREA、REQUIRE_MEMORY、THREAD_RESIDENCE_MEMORY分别对应于图2-1、图2-2、图2-3中的一行,不同之处是为了构成链表在三个结构体中都有前向指针。数组init_free_area_table对应于图2-6,数组init_thread_require_memory_table对应于图2-5,数组init_thread_residence_memory_table对应于图2-7,为了实现动态分配与释放,用链表重新组织空闲区域表、线程驻留区表和内存申请表,全局变量p_free_area_list是空闲区链首,p_thread_require_memory_queue是内存申请队列的队首,p_thread_residence_memory_list是线程驻留区链首,tail_thread_residence_memory_list是线程驻留区链尾,由于线程驻留区链表被内存分配函数和内存释放函数共享,故用临界区变量CS_THREAD_MEMORY_LIST来保护,同理,屏幕是所有线程共享的,所以用临界区变量CS_SCREEN来保护,空闲区链表被内存分配函数和内存释放函数共享,故用临界区变量CS_FREEAREA_LIST来保护。h_thread是线程句柄数组,用来存放各个线程的句柄。 程序共包含13个函数,按照作用可以将它们分成五组。 第一组包括函数print_space()和函数display_thread_residence_memory(),前者用来显示若干个空格,后者用来显示线程驻留区表; 第二组共十一个函数,用来实现最佳适应分配法,它们的名称及功能如图2-9。 函数名称 函数功能 BF_initialize_freearea_list 初始化空闲区链表:按长度递增排序 BF_delete_freearea_list 删除空闲区链表 BF_initialize_require_memory_list 初始化内存申请链表 BF_delete_require_memory_list 删除内存申请链表 BF_initialize_thread_residence_memory_list 初始化线程驻留区链表 BF_delete_thread_residence_memory_list 删除线程驻留区链表 BF_thread 线程函数:申请内存;驻留内存;释放内存 BF_require_memory 申请一段内存,成功时返回起始地址,失败时返回空 BF_release_memory 释放一段内存 BF_insert_freearea 将空闲区按大小递增的次序插入到空闲区链表中 BF() 初始化函数:创建线程并等待它们结束 图2-9 最佳适应分配法的函数及其功能 2.3.5 参考源代码 下面是部分程序的源代码清单。 头文件 variable_partition.h 的清单 #include <windows.h> #include <conio.h> #include <stdlib.h> #include <stdio.h> #include <io.h> #include <string.h> #define MAX_THREAD 3 typedef struct freearea{ //表示空闲区域的数据结构 struct freearea *next; //指向下一个结点的指针 int start_address; //空闲区起始地址 int size; //空闲区大小 }FREEAREA; typedef struct require_memory{ //记录线程申请内存的数据结构 struct require_memory *next; //指向下一个结点的指针 char thread_name[10]; //线程名 int size; //申请内存大小(以KB为单位) int duration; //在内存的驻留时间(以秒为单位) }REQUIRE_MEMORY; typedef struct thread_residence_memory{ //描述线程驻留区的数据结构 struct thread_residence_memory *next; //指向下一个结点的指针 char thread_name[10]; //线程名 int start_address; //驻留区起始地址 int size; //驻留区大小 }THREAD_RESIDENCE_MEMORY; FREEAREA init_free_area_table[5]={ {NULL,10,10}, {NULL,40,30}, {NULL,80,5}, {NULL,145,15}, {NULL,180,20} }; //测试数据:初始空闲区表 REQUIRE_MEMORY init_thread_require_memory_table[3]={ {NULL,"thread_1",20,4}, {NULL,"thread_2",10,5}, {NULL,"thread_3",5,6} }; //测试数据:初始内存申请表 THREAD_RESIDENCE_MEMORY init_thread_residence_memory_table[5]={ {NULL,"a",0,10}, {NULL,"b",20,20}, {NULL,"c",70,10}, {NULL,"d",85,60}, {NULL,"e",160,20} };//测试数据:初始线程驻留区表 FREEAREA *p_free_area_list=NULL; //空闲区链首 REQUIRE_MEMORY *p_thread_require_memory_queue=NULL; //内存申请队列队首 THREAD_RESIDENCE_MEMORY *p_thread_residence_memory_list=NULL; //线程驻留链首 THREAD_RESIDENCE_MEMORY *tail_thread_residence_memory_list=NULL; //线程驻留区链尾 CRITICAL_SECTION CS_THREAD_MEMORY_LIST; //保护线程驻留区链表的临界区 CRITICAL_SECTION CS_SCREEN; //保护屏幕的临界区 CRITICAL_SECTION CS_FREEAREA_LIST; //保护空闲区链表的临界区 HANDLE h_thread[MAX_THREAD]; //线程句柄数组 void print_space(int num); //输出若干个空格 void display_thread_residence_memory_list(); //显示线程驻留区表 //最佳适应分配算法的函数 void BF_thread(void *data); //线程函数 void BF_delete_freearea_list(); //删除空闲区链表 REQUIRE_MEMORY *BF_initialize_require_memory_list(REQUIRE_MEMORY *init_table,int num); //初始化内存申请链表 void BF_delete_require_memory_list(); //删除内存申请链表 THREAD_RESIDENCE_MEMORY *BF_initialize_thread_residence_memory_list (THREAD_RESIDENCE_MEMORY *init_table,int num); //初始化线程驻留区链表 void BF_delete_thread_residence_memory_list(); //删除线程驻留区链表 int BF_require_memory(int size); //内存申请函数 void BF_release_memory(int start_address,int size); //内存释放函数 void BF_insert_freearea(FREEAREA *free_node); //空闲区结点插入函数 void BF(); //初始化程序 void BF_initialize_freearea_list(FREEAREA *init_table,int num); //初始化空闲区链表 源程序文件 variable_partition.cpp 的清单 #include "variable_partition.h" void print_space(int num){ //显示若干个空格 int i; for(i=0;i<num;i++){ printf(" "); } } void display_thread_residence_memory_list(){ //显示驻留线程链表 THREAD_RESIDENCE_MEMORY *p; char buffer[20]; p=p_thread_residence_memory_list; printf("|-------------------|--------------------|------------------|\n"); printf("| thread_name | start_address(kB) | size(KB) |\n"); printf("|-------------------|--------------------|------------------|\n"); while(p!=NULL){ printf("| %s",p->thread_name); print_space(18-strlen(p->thread_name)); printf("| %d",p->start_address); itoa( p->start_address, buffer, 10 ); print_space(19-strlen(buffer)); printf("| %d",p->size); itoa(p->size, buffer, 10 ); print_space(17-strlen(buffer)); printf("|\n"); p=p->next; }; printf("|-------------------|--------------------|------------------|\n\n"); } //最佳适应分配法:删除空闲区链表 void BF_delete_freearea_list(){ FREEAREA *temp; temp=p_free_area_list; while(temp!=NULL){ temp=p_free_area_list->next; free(p_free_area_list); p_free_area_list=temp; } p_free_area_list=NULL; } //最佳适应分配法:初始化内存申请链表 REQUIRE_MEMORY *BF_initialize_require_memory_list(REQUIRE_MEMORY *init_table,int num){ REQUIRE_MEMORY *temp; REQUIRE_MEMORY *head=NULL; REQUIRE_MEMORY *tail=NULL; int i; for(i=0;i<num;i++){ temp=(REQUIRE_MEMORY *)malloc(sizeof(REQUIRE_MEMORY)); strcpy(temp->thread_name,init_table[i].thread_name); temp->size=init_table[i].size; temp->duration=init_table[i].duration; temp->next=NULL; if(head==NULL) head=tail=temp; else{ tail->next=temp; tail=tail->next; } }; return head; } //最佳适应分配法:删除内存申请链表 void BF_delete_require_memory_list(){ REQUIRE_MEMORY *temp; temp=p_thread_require_memory_queue; while(temp!=NULL){ temp=p_thread_require_memory_queue->next; free(p_thread_require_memory_queue); p_thread_require_memory_queue=temp; } p_thread_require_memory_queue=NULL; } //最佳适应分配法:初始化线程驻留区链表 THREAD_RESIDENCE_MEMORY *BF_initialize_thread_residence_memory_list(THREAD_RESIDENCE_MEMORY *init_table,int num){ THREAD_RESIDENCE_MEMORY *temp; THREAD_RESIDENCE_MEMORY *head=NULL; THREAD_RESIDENCE_MEMORY *tail=NULL; int i; for(i=0;i<num;i++){ temp=(THREAD_RESIDENCE_MEMORY *)malloc(sizeof(THREAD_RESIDENCE_MEMORY)); strcpy(temp->thread_name,init_table[i].thread_name); temp->start_address=init_table[i].start_address; temp->size=init_table[i].size; temp->next=NULL; if(head==NULL) head=tail=temp; else{ tail->next=temp; tail=tail->next; } }; tail_thread_residence_memory_list=tail; return head; } //最佳适应分配法:删除线程驻留区链表 void BF_delete_thread_residence_memory_list(){ THREAD_RESIDENCE_MEMORY *temp=p_thread_residence_memory_list; temp=p_thread_residence_memory_list; while(temp!=NULL){ temp=p_thread_residence_memory_list->next; free(p_thread_residence_memory_list); p_thread_residence_memory_list=temp; } p_thread_residence_memory_list=NULL; } //最佳适应分配算法的线程:申请内存,驻留一段时间,释放内存 void BF_thread(void *data){ int start_address=-1; THREAD_RESIDENCE_MEMORY *temp; EnterCriticalSection(&CS_SCREEN); printf("create thread:%s\n",((REQUIRE_MEMORY *)(data))->thread_name); LeaveCriticalSection(&CS_SCREEN); //申请内存 while(1){ start_address=BF_require_memory(((REQUIRE_MEMORY *)(data))->size); if(start_address>=0) break; else Sleep(1000); } temp=(THREAD_RESIDENCE_MEMORY *)malloc(sizeof(THREAD_RESIDENCE_MEMORY)); strcpy(temp->thread_name,((REQUIRE_MEMORY *)(data))->thread_name); temp->start_address=start_address; temp->size=((REQUIRE_MEMORY *)(data))->size; temp->next=NULL; EnterCriticalSection(&CS_THREAD_MEMORY_LIST); //加入线程内存驻留区链表 tail_thread_residence_memory_list->next=temp; tail_thread_residence_memory_list=tail_thread_residence_memory_list->next; LeaveCriticalSection(&CS_THREAD_MEMORY_LIST); //显示线程内存驻留区链表 EnterCriticalSection(&CS_SCREEN); printf("after %s %s\n",((REQUIRE_MEMORY *)(data))->thread_name,"get memory:"); display_thread_residence_memory_list(); LeaveCriticalSection(&CS_SCREEN); Sleep(((REQUIRE_MEMORY *)(data))->duration); //释放内存 BF_release_memory(start_address,((REQUIRE_MEMORY *)(data))->size); } //最佳适应分配算法的内存申请函数 int BF_require_memory(int size){ //请读者自己实现这段代码 } //最佳适应分配算法的内存释放函数 void BF_release_memory(int start_address,int size){ //请读者自己实现这段代码 } //最佳分配算法的空闲区结点插入函数 void BF_insert_freearea(FREEAREA *free_node){ FREEAREA *p; FREEAREA *p_next; if(p_free_area_list==NULL) p_free_area_list=free_node; else{ p_next=p=p_free_area_list; while(p_next!=NULL&&p_next->size<free_node->size){ p=p_next; p_next=p_next->next; } if(p_next==NULL) //应插入到尾部 p->next=free_node; else if(p==p_next){ //应插入到头部 free_node->next=p; p_free_area_list=free_node; } else{ //应插入到p与p_next之间 free_node->next=p_next; p->next=free_node; } } } //最佳适应分配法:初始化空闲区链表 void BF_initialize_freearea_list(FREEAREA *init_table,int num){ FREEAREA *temp; int i; for(i=0;i<num;i++){ temp=(FREEAREA *)malloc(sizeof(FREEAREA)); temp->start_address=init_table[i].start_address; temp->size=init_table[i].size; temp->next=NULL; BF_insert_freearea(temp); } } //最佳分配算法的初始化程序 void BF( ) { int i=0; REQUIRE_MEMORY *p; HANDLE h_thread[MAX_THREAD]; InitializeCriticalSection(&CS_THREAD_MEMORY_LIST); InitializeCriticalSection(&CS_FREEAREA_LIST); InitializeCriticalSection(&CS_SCREEN); printf("最佳适应分配算法\n"); BF_initialize_freearea_list(init_free_area_table,5); p_thread_require_memory_queue=BF_initialize_require_memory_list(init_thread_require_memory_table,3); p_thread_residence_memory_list=BF_initialize_thread_residence_memory_list(init_thread_residence_memory_table,5); p=p_thread_require_memory_queue; while(p!=NULL){ h_thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(BF_thread),p,0,NULL); i++; p=p->next; }; //等待所有线程结束 WaitForMultipleObjects(MAX_THREAD,h_thread,TRUE,-1); //显示驻留线程链表 EnterCriticalSection(&CS_SCREEN); printf("after all threads have finished:\n"); display_thread_residence_memory_list(); LeaveCriticalSection(&CS_SCREEN); //删除各种链表 BF_delete_freearea_list(); BF_delete_require_memory_list(); BF_delete_thread_residence_memory_list(); getch(); printf("\n"); } void main( ){ BF( ); }根据上面的要求和部分代码,补充上面代码实现动态异长分区内存分配与去配算法的设计-最佳适应算法
05-28
<think>好的,用户想实现动态异长分区内存分配与回收的最佳适应算法,具体需要补充内存申请函数BF_require_memory和内存释放函数BF_release_memory。首先,我得理解用户提供的代码框架中的数据结构。根据引用[1],结构体FREEAREA、REQUIRE_MEMORY、THREAD_RESIDENCE_MEMORY都有前向指针,可能用于链表。空闲区链表由p_free_area_list指向,内存申请队列是p_thread_require_memory_queue,线程驻留区链表是p_thread_residence_memory_list和tail_thread_residence_memory_list。临界区变量用于保护共享资源,比如CS_FREEAREA_LIST保护空闲区链表。接下来,最佳适应算法(Best Fit)要求在分配时找到能满足请求的最小空闲块。所以,在BF_require_memory函数中,需要遍历空闲区链表,找到大小最接近且大于等于所需内存的块。如果找到,分配后剩余的部分要作为新的空闲区插入链表。这里需要注意临界区的保护,操作链表前要进入临界区,操作完后离开。 对于内存释放函数BF_release_memory,当释放一个内存块时,需要将其合并到空闲区链表中,并处理可能的前后相邻空闲区合并问题。同样需要临界区保护,遍历链表找到合适的位置,检查前后是否有相邻的空闲区,合并后更新链表。然后,考虑代码实现的具体步骤。申请函数的大致流程是:遍历空闲链表,找到最佳块;分割该块,分配所需部分,剩余部分作为新节点插入;更新链表。释放函数则需要处理合并,可能需要四个情况:与前一块合并,与后一块合并,同时合并前后,或不合并直接插入。同时要注意线程驻留区链表的操作,可能需要从链表中移除已释放的块。还要注意数据结构的具体成员,比如FREEAREA结构体可能包含起始地址、大小、前后指针等。在分配时,需要修改这些指针来维护链表结构。另外,内存申请队列可能是一个队列结构,需要处理线程的请求排队问题,但根据用户的问题,可能只需要处理最佳适应算法,这部分可能不需要修改队列结构,而是直接处理空闲链表。 最后,验证实现的正确性,比如分配时是否正确找到最小块,释放时是否正确合并,临界区是否正确使用,避免竞态条件。同时,参考引用[2]提到的不同算法的优缺点,最佳适应算法可能产生较多碎片,但在实验中需要正确实现其逻辑。</think>根据提供的代码框架,实现最佳适应算法需要结合空闲区链表管理和临界区保护机制。以下是分步骤实现方案: ### 一、内存申请函数BF_require_memory实现 ```c void BF_require_memory(int tid) { EnterCriticalSection(&CS_FREEAREA_LIST); EnterCriticalSection(&CS_THREAD_MEMORY_LIST); // 从线程申请队列获取需求 REQUIRE_MEMORY* req = find_thread_request(tid); FREEAREA* best_fit = NULL; FREEAREA* current = p_free_area_list; // 遍历寻找最小可用块 while(current) { if(current->size >= req->size && (!best_fit || current->size < best_fit->size)) { best_fit = current; } current = current->next; } if(best_fit) { // 分配内存并分割剩余空间 THREAD_RESIDENCE_MEMORY* alloc = create_allocation(best_fit->start, req->size); best_fit->start += req->size; best_fit->size -= req->size; // 若剩余空间为0则移除该空闲块 if(best_fit->size == 0) { remove_from_free_list(best_fit); } // 添加到驻留区链表 add_to_residence_list(alloc); } LeaveCriticalSection(&CS_THREAD_MEMORY_LIST); LeaveCriticalSection(&CS_FREEAREA_LIST); } ``` ### 二、内存释放函数BF_release_memory实现 ```c void BF_release_memory(int tid) { EnterCriticalSection(&CS_FREEAREA_LIST); EnterCriticalSection(&CS_THREAD_MEMORY_LIST); // 查找要释放的分配块 THREAD_RESIDENCE_MEMORY* alloc = find_allocation(tid); FREEAREA* new_free = create_free_area(alloc->start, alloc->size); // 合并相邻空闲区 FREEAREA* prev = NULL; FREEAREA* curr = p_free_area_list; while(curr && curr->start < new_free->start) { prev = curr; curr = curr->next; } // 前向合并 if(prev && prev->start + prev->size == new_free->start) { prev->size += new_free->size; new_free = prev; } else { insert_into_free_list(new_free, prev); } // 后向合并 if(curr && new_free->start + new_free->size == curr->start) { new_free->size += curr->size; remove_from_free_list(curr); } // 从驻留链表移除 remove_from_residence_list(alloc); LeaveCriticalSection(&CS_THREAD_MEMORY_LIST); LeaveCriticalSection(&CS_FREEAREA_LIST); } ``` ### 关键实现要点: 1. **空闲区管理**:使用带头结点的双向链表存储空闲区,每个节点包含$start$、$size$和前后指针[^1] 2. **临界区保护**:操作链表时必须使用`EnterCriticalSection`/`LeaveCriticalSection`保护共享资源 3. **合并策略**:释放时需处理四种合并情况: - 仅与前空闲区合并 - 仅与后空闲区合并 - 同时合并前后空闲区 - 无需合并直接插入 ### 性能优化建议: 1. 使用平衡树替代链表可将查找时间从$O(n)$降至$O(\log n)$ 2. 预分配空闲区描述符减少动态内存分配 3. 采用延迟合并策略减少临界区占用时间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值