首页 > 其他分享 >【无标题】

【无标题】

时间:2024-05-26 22:32:32浏览次数:12  
标签:mymalc mem struct 无标题 内存 size cur

操作系统实验报告4

实验四 内存分配器的实现

  • 实习编号:操作系统实验_实验_4
  • 实习名称:内存分配器的实现
  • 巩固知识点
  1. 了解并熟悉Linux操作系统的常用命令操作;
  2. 了解基于Linux的功能开发。
  • 实习对应培养点
  1. 学习使用Linux环境编写C程序;
  2. 学习内存管理的开发相关知识。
  • 实验目的
  1. 熟悉掌握基于Linux的程序开发环境配置与使用;
  2. 熟悉掌握常用内存管理开发知识点以及系统指令。
  • 实验内容和步骤

【任务1】 实现简单的内存分配器

C语言中内存在使用之前必须为其分配空间,使用结束后要释放,否则会发生内存泄漏。申请和释放内存空间使用malloc和free这两个函数。malloc申请的空间在程序的堆中。本实验就是要你实现你自己的mymalloc和myfree,利用标准库的malloc链表去模拟实现简单的内存分配器,实现mymalc.c文件。

函数原型如下:

void *mymalloc(int size);   //分配大小为size的一块内存

void myfree(void *ptr);      //释放ptr指针指向的一块内存

实现提示:

1、为了简单起见,我们的程序在运行开始时预先申请了一块内存作为我们的堆:

#define MAXMEM 64000

2、我们的堆里的每一块内存均有一个结构mymalc描述,不管这个内存块是空闲的还是已被分配的,这个结构描述如下:

struct mymalc

{

    int id;

    int size;

    int status;                //  0:自由;1:已分配

    char *p;                   // 指向返回给用户的指针

    struct mymalc *nextchunk;  // 指向下一个内存块

};

所有的mymalc构成了一个单链表,表头指针是一个全局变量

struct  mymalc *my_mem_head;

链表的每一个节点之后紧跟的是一块大小为size的内存块。

3、你的程序开始时,需要首先调用myinit():             

void myinit() {   //初始化你的内存分配系统

    my_mem_head=(struct  mymalc *)malloc(MAXMEM);

    my_mem_head->id=1;

    my_mem_head->status=0;

    my_mem_head->nextchunk=NULL;

my_mem_head->p=(char *)my_mem_head+sizeof(struct mymalc); // p represents the block of data

    my_mem_head->size=MAXMEM - sizeof(struct mymalc); // available size should exclude the size of the block of meta data

}

显然,你的程序刚开始运行时,这个链表只有一个节点,整个堆空间是一个大的自由空间。随着你的程序的逐步运行,这个堆空间会变得支离破碎,链表也有了多个节点。

4、实现以下3个函数完成内存分配管理的模拟功能:

(1) mymalloc函数所完成的功能是根据应用所需要申请的内存数量,在堆中分配指定的数量内存。大致过程:在链表中找到一块大于要求数量的空闲内存,将这块内存一分为二,一部分分配给应用,另一部分标识为空闲,修改内存链表。

(2)myfree释放指定的内存。释放掉的内存如果前面或后面也是空闲块,需要将相邻的空闲块合并

(3)disp_mem_link便于调试使用。该函数的作用是打印出目前内存链表中各个节点的相关信息,比如数据块编号、size、是否空闲以及p的指针。

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#define MAXMEM 64000 //划定最大堆区内存
int id = 0;//初始化id
struct mymalc//内存块结构
{
	int id;
    int size;
    int status;
	char *p; 
	struct mymalc *nextchunk; 
};

struct mymalc* head_mem = NULL;

void initialize_headmem()//初始化堆区首节点
{
	head_mem =(struct mymalc*)malloc(MAXMEM);//申请MAXMEM大小的堆区内存给head_mem
	head_mem->id = id++;
	head_mem->size = MAXMEM-sizeof(struct mymalc);
	head_mem->status = 0;
	head_mem->nextchunk = NULL;
	head_mem->p = (char*)head_mem+sizeof(struct mymalc);
	printf("初始化成功!\n");
	printf("目前总可用内存为size:%d\n",head_mem->size);
}

char* my_malloc(int need_size)//开辟新节点并分配内存
{
	struct mymalc* cur = head_mem;
	//struct mymalc* pre = NULL; 
	struct mymalc* id_max =  head_mem;
	//while(1)
	{
		
	}
	
	while(cur!=NULL)
	{
		if(cur->status == 0&&cur->size>=need_size)//
		{
			if(cur->size>need_size+sizeof(struct mymalc))//创建新内存块
			{
				struct mymalc* new_mem = (struct mymalc*)(cur->p + need_size);
				new_mem->size = cur->size - need_size - sizeof(struct mymalc);
				new_mem->nextchunk = NULL;
				new_mem->p = (char*)new_mem + sizeof(struct mymalc);
				new_mem->id = id++;
				new_mem->status = 0;
				cur->size = need_size;
				new_mem->nextchunk = cur->nextchunk;
				cur->nextchunk = new_mem;
			}
			printf("内存开辟成功\n");
			cur->status = 1;
			return cur->p;
		}
		cur = cur->nextchunk;
	}
	printf("内存开辟失败\n");
	return NULL;
}

void my_free(char *ptr)//释放当前指针内存
{
	struct mymalc* cur = head_mem;
	struct mymalc* pre = NULL;
	while(cur!=NULL)
	{	
		if(cur->p==ptr)
		{
			break;
		}	
		pre = cur;	
		cur = cur->nextchunk;
	}
	if(cur==NULL||cur->status == 0)
	{
		if(cur == NULL)
		printf("未找到对应地址\n");
		else 
		printf("该地址已经释放\n");
		return;
	}
	
	if(pre != NULL&&cur->nextchunk!=NULL)//该地址前后内存块status均为0,前后内存合并
	{
		if(pre->status == 0&&cur->nextchunk->status == 0)//该判断位于cur->nextvhunk!=NULL,避免内存非法访问
		{
			pre->size = pre->size + cur->size + cur->nextchunk->size + 2*sizeof(struct mymalc);
			pre->nextchunk = cur->nextchunk->nextchunk;
			return;
		}
	}
	
	if(cur->nextchunk!=NULL)//该地址后的内存块也为0,后内存合并
	{
		if(cur->nextchunk->status == 0)
		{
			cur->size = cur->size + cur->nextchunk->size + sizeof(struct mymalc);
			cur->nextchunk = cur->nextchunk->nextchunk;
			cur->status = 0;
			return;
		}
	}
	
	if(pre != NULL)//该地址的前内存块也为0,前内存合并
	{
		if(pre->status == 0)
		{
			pre->size = pre->size + cur->size + sizeof(struct mymalc);
			pre->nextchunk = cur->nextchunk;
			return;
		}
	}
	
	//前后均不为0
	{
		printf("!\n");
		cur->status = 0;
	}
}


void disp_memchunk()//逐个打印内存块信息
{
	struct mymalc* cur = head_mem;
	while(cur != NULL)
	{
		printf("id:%d\t",cur->id);
		printf("size:%d\t",cur->size);
		printf("status:%d\n",cur->status);
		printf("p:%p\n",cur->p);
		cur = cur->nextchunk;
	}
}

int main()
{
	head_mem = (struct mymalc*)malloc(sizeof(struct mymalc));
	initialize_headmem();
	char *p1, *p2, *p3;
	char *p[10];
	int a = 0, i;
	printf("-------------Test stage 1 ------------------------\n");
	p1 = my_malloc(99);
	p2 = my_malloc(999);
	disp_memchunk();
	printf("p1=%p\n", (void *)p1);
	my_free(p1);
	disp_memchunk();
	printf("\n");
	
	p3 = my_malloc(51);
	disp_memchunk();
	printf("p3=%p\n", (void *)p3);
	printf("\n");
	
	my_free(p2);
	disp_memchunk();
	printf("\n");
	
	my_free(p3);
	disp_memchunk();
	printf("\n");
	
	printf("-------------Test stage 2 ------------------------\n");
	a = 64;
	for (i = 0; i < 10; i++) {
		p[i] = my_malloc(a);
		printf("p[%d]=%p  \n", i, (void *)p[i]);
	}
	disp_memchunk();
	printf("\n");
	
	my_free(p[2]);
	disp_memchunk();
	printf("\n");
	
	my_free(p[3]);
	disp_memchunk();
	printf("\n");
	
	my_free(p[4]);
	p1 = my_malloc(1500);
	disp_memchunk();
	return 0;

	
}

标签:mymalc,mem,struct,无标题,内存,size,cur
From: https://blog.csdn.net/s1117f/article/details/139221118

相关文章

  • 【无标题】
    CSS选择器以及权重问题选择器:就是给标签取名字一、选择器的类型1、标签(类型)选择器:(权重为1)标签选择器可以对所有的同类标签起作用,对应标签div/p/i/strong语法:标签{属性:属性值;}应用场景:需要统一或者清除标签内容的样式时;2、id选择器:(权重为100)语法:在标签内给用id给标......
  • 【无标题】基于[具体技术]的烟雾识别算法研究
    本文主要探讨了一种高效的烟雾识别算法,通过对[相关技术或特征]的分析和利用,实现了对烟雾的准确检测和识别。详细介绍了算法的原理、流程以及实验结果,并结合实际应用案例展示了其应用价值。一、引言(阐述烟雾识别的重要性及应用场景)二、相关工作(回顾以往烟雾识别算法的研究......
  • 【无标题】
    Web_Person简单的制作一个个人主页。在这里面我们需要制作一个表头,Tabs导航栏。这个·做的比较简单,所以比较复杂的东西。表头先自定义一个组件制作表头,这里面的使用的Text、Image和Button组件。并且我们需要在Texr添加点击事件:页面返回到上一级。@Componentstruct Head1......
  • 【无标题】Spark基础编程
    一、创建RDD    1.从内存中创建RDD      (1)parallelize()方法       (2)makeRDD()方法通过Linux本地文件创建RDD 二,使用map方式转换数据  使用sortBy方式转换数据  用collect方法查询数据flat方法转换数据 take方法 ......
  • 【无标题】
    #设计猫类,属性有种类|、颜色、年龄和体重,方法有输出猫的信息、猫发出叫声、猫玩东西packagedemo;classCat{privateStringspecies;//种类privateStringcolor;//颜色privateintage;//年龄privatedoubleweight;//体重//构造......
  • 【无标题】idea 中 SpringBoot 点击运行没反应,按钮成灰色
    问题描述在使用SpringBoot开发项目时,可能会遇到一个问题:点击运行按钮后,控制台没有任何输出,项目界面也没有显示。这种情况可能是由多种原因导致的,本文将介绍一些常见的解决方法。解决方法首先看下Groovy插件是否选择,取消选择1.检查端口是否被占用首先,我们需要检查应用程......
  • 【无标题】
    本书教你两件事机器学习模型及其使用方法。机器学习模型有不同的类型。有些返回确定性的答案,例如是或否,而另一些返回概率性的答案。有些以问题的形式呈现;其他则使用假设性表达。这些类型的一个共同点是它们都返回一个答案或一个预测。比如,返回预测的模型的机器学习分支被命名......
  • 【无标题】
    一、@charset"字符编码形式"作用:在CSS文件的最开始处使用这个指令可以告诉浏览器以UTF-8编码解释样式表。如果你使用这个指令,重要的是要确保你的CSS文件实际上是以UTF-8编码保存的例如:@charset"UTF-8";@charset"iso-8859-15";语法格式:@charset  "<char......
  • 【无标题】
    CREATETABLE`student`(`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'学号',`createDate`datetimeDEFAULTNULL,`userName`varchar(20)DEFAULTNULL,`pwd`varchar(36)DEFAULTNULL,`phone`varchar(11)DEFAULTNULL,`age`tinyint(3)D......
  • 【无标题】计算机图形学OpenGL基础
    一、OpenGL的主要功能模型绘制模型观察颜色模式光照应用图像效果增强位图和图像处理纹理映射实时动画交互技术二、OpenGL的绘制流程----------工作方式**一个完整的窗口系统的OpenGL图形处理系统的结构为:最底层为图形硬件,第二层为操作系统,第三层为窗口系统,第四层为OpenG......