Linux系统---简易伙伴系统

顾得泉:个人主页

个人专栏:《Linux操作系统》  《C/C++》  《LeedCode刷题》

键盘敲烂,年薪百万!


一、题目要求

1.采用C语言实现

2.伙伴系统采用free_area[11]数组来组织。要求伙伴内存最小为一个页面,页面大小为4KB,最大为4MB,即1024个页面。描述一个空闲伙伴内存块的数据结构为

struct chunk
{

       unsigned int power;  //内存块大小的2次幂指数,如12,13,...,22

       unsigned int start;   //内存块的起始地址

       struct chunk* next;  //后向指针

       Struct chunk* prev;  //前向指针

}

3.如何辨识两个内存块c1和c2互为伙伴(buddy)?

  条件1:c1.power=c2.power,即两个块的大小相同;

  条件2:c1和c2的地址start(二进制)的第power位不同,其他位完全相同。比如,大小为256KB的两个伙伴,一个地址为0x0000,0000,另一个为0x0004,0000,这两个地址的第18位(二进制位,从0开始起位)一个为0,一个为1,其余位完全相同,因此它们互为buddy。

       再如,大小为256KB的两个伙伴,一个地址为0x0008,0000,另一个为0x000C,0000,它们的第power位,即第18位一个为0,一个为1,其余位完全相同。

       而地址为0x4,0000和0x8,0000的chunk不是伙伴,尽管它们是相邻的。

       因此可以设计判断两个chunk是否是伙伴的函数:

int isBuddy(struct chunk* c1, struct chunk* c2)

{

    if(c1->power!=c2->power)

        return 0;

    if((c1->start^c2->start)>>c1->power!=1) //先异或,再移位

        return 0;

    return 1;

}

二、模块描述

       本文实现了一个内存管理程序,用于分配和释放内存块。它使用了内存池技术,通过将内存块划分为大小为2^n的块来提高内存分配的效率。

程序中定义了一个结构体chunk,表示内存块,包含以下成员变量:

  • power:表示内存块的大小,即2^n。
  • start:表示内存块的起始地址。
  • next:指向下一个内存块的指针。
  • prev:指向上一个内存块的指针。

       程序还定义了一个全局数组free_area,用于存储空闲的内存块。数组的索引表示内存块的大小,数组的元素是指向对应大小的内存块链表的头指针。

程序提供了以下函数:

  • is_buddy(struct chunk *c1 , struct chunk *c2):判断两个内存块是否为“伙伴”关系,即它们的power相同且它们的起始地址相邻。
  • init():初始化内存池,将最大内存块分配给free_area[8]
  • pick(unsigned int k):从free_area中选择一个大小为2^k的内存块,并将其分割成两个大小为2^(k-1)的内存块。
  • allocate(unsigned int req):请求分配一个大小为req字节的内存块,如果无法满足请求,则返回NULL。
  • release(struct chunk *c):释放一个内存块,将其与相邻的伙伴内存块合并,并更新free_area
  • check():打印当前内存池的状态,包括每个大小的内存块链表。

       在main()函数中,首先调用init()函数初始化内存池,然后依次请求分配100KB、256KB和500KB的内存块,并打印分配前后的内存池状态。最后,释放这些内存块,并再次打印内存池状态。


三、代码实现

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

struct chunk{
    unsigned int power;
    unsigned int start;
    struct chunk *next;
    struct chunk *prev;
};

struct chunk* free_area[11];

int is_buddy(struct chunk *c1 , struct chunk *c2)
{
    if(c1 -> power != c2 -> power) return 0;
    if((c1 -> start ^ c2 -> start) >> c1 -> power != 1) return 0;
    return 1;
}

void init()
{
    for(int i = 0 ; i < 11 ; i ++)
    free_area[i] = NULL;

    struct chunk *max_chunk = (struct chunk*) malloc(sizeof(struct chunk));
    max_chunk -> power = 20;
    max_chunk -> start= 0;
    max_chunk -> next = NULL;
    max_chunk -> prev = NULL;
    free_area[8] = max_chunk;
}

struct chunk *pick(unsigned int k)
{
    struct chunk *c = NULL;
    struct chunk *left = NULL;
    struct chunk *right = NULL;

    int i;
    for(i = k ; i <= 10 ; i ++)
    {
        if(free_area[i] != NULL)
        {
            c = free_area[i];
            free_area[i] = c -> next;
            break;
        }
    }


    if(i > 10){
        printf("Failed to pick up a trunk\n");
        return NULL;
    }


    for(int j = i - 1 ; j >= k ; j --)
    {
        left = (struct chunk*)malloc(sizeof(struct chunk));
        left -> power = c -> power - 1;
        left -> start = c -> start;
        left -> next = free_area[j];
        left -> prev = NULL;
        if(free_area[j] != NULL)
        {
            free_area[j] -> prev = left;
        }
        free_area[j] = left;

        right = (struct chunk *) malloc(sizeof (struct chunk));
        right -> power = c -> power - 1;
        right -> start = c -> start + (1 << right -> power);
        right -> next = NULL;
        right -> prev = NULL;

        free(c);
        c = right;
    }

    return c;
}



struct chunk * allocate(unsigned int req){
    unsigned int power = 0;
    while((1 << power) < req)
        power ++;
    return pick(power - 12);

}


void release(struct chunk *c)
{
    unsigned int k = c -> power - 12;
    struct chunk * buddy = NULL;

    int merged = 1;
    while(merged){
        merged = 0;
        buddy = free_area[k];

        while(buddy != NULL){
            if(is_buddy(c , buddy))
            {
                 c -> power ++;
                 if(buddy -> prev == NULL)
                 free_area[k] = buddy -> next;
                 else 
                    buddy -> prev -> next = buddy -> next;
                 if(buddy -> next != NULL)
                    buddy -> next -> prev = buddy -> prev;

                    if(c -> start > buddy -> start) 
                        c -> start = buddy -> start;

            free(buddy);
            merged = 1;
            k ++;
            break;
       }
       buddy = buddy -> next;
    }
    }


    c -> next = free_area[k];
    if(free_area[k] != NULL)
        free_area[k] -> prev = c;
     free_area[k] = c;
}

void check()
{
    for(int i = 0 ; i < 11 ; i ++)
    {
      printf("free_area[%d]: " , i);
      struct chunk * chunk = free_area[i];
      while(chunk != NULL)
      {
        printf("(%u  , %x) ->" , chunk -> power , chunk -> start);
        chunk = chunk -> next;
      }
       printf("NULL\n");
    }
    printf("\n");
}


int main()
{
    init();
    printf("inintal state\n");
    check();

    struct chunk *c100 = allocate(100 * 1024);
    printf("ask for 100kb allocate\n");
    check();

    struct chunk *c256 = allocate(256 * 1024);
    printf("ask for 256kb allocate\n");
    check();

    struct chunk *c500 = allocate(500 * 1024);
    printf("ask for 500kb allocate\n");
    check();


    release(c100);
    printf("release c100\n");
    check();

    release(c256);
    printf("release c256\n");
    check();

    release(c500);
    printf("release c500\n");
    check();
}

四、结果展示

首先开辟了一块1M大小的空间:

请求分配100KB的内存块:

请求分配256KB的内存块:

请求分配500KB的内存块:

释放100KB的内存块:

释放256KB的内存块:

释放500KB的内存块:

到此所有操作就结束了。


结语:Linux系统中实现简易的伙伴系统的分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/233060.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言习题

写一个函数&#xff0c;输入一个四位数字&#xff0c;要求输出这四个数字字符&#xff0c;但每两个数字间空一个空格。如输入1990&#xff0c;输出1 9 9 0 如下&#xff1a; #include<stdio.h> void Print(int n) { if(n>9) { Print(n/10); } printf("%d "…

ssm的健身房预约系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; ssm的健身房预约系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Spring…

【trino权威指南】使用trino详解:trino client安装、查询sql、DBeaver连接trino、java通过JDBC连接trino

文章目录 一. Trino CLI1. 安装client2. 使用client执行sql 二. JDBC driver 连接Trino1. 通过DBeaver用户界面连接2. JDBC Driver in java2.1. 环境配置2.2. 注册和配置driver2.3. 连接参数2.4. 查询例子 一. Trino CLI 1. 安装client Trino CLI提供了一个基于终端的交互式s…

H264之NALU结构详解

摘要&#xff1a;本文详细描述了AVC的NALU的码流结构&#xff0c;以及各个层面上NALU详细的构成。   关键字&#xff1a;AVC&#xff0c;NALU 1 NALU简介 NAL层即网络抽象层&#xff08;Network Abstraction Layer&#xff09;&#xff0c;是为了方便在网络上传输的一种抽象…

tomcat篇---第四篇

系列文章目录 文章目录 系列文章目录前言一、为什么我们将tomcat称为Web容器或者Servlet容器 ?二、tomcat是如何处理Http请求流程的?三、tomcat结构目录有哪些?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这…

Mysql索引一篇就够了

索引 定义 索引是对数据库表中一列或者多列的值进行排序的结构。 目的 数据库索引好比一本书的目录&#xff0c;提高查询效率。但是为表设置索引要付出相应的代价&#xff1a; 增加了数据库的存储空间 在插入和修改时需花费更多的时间&#xff08;因为索引也要随之变动&#…

带有 RaspiCam 的 Raspberry Pi 监控和延时摄影摄像机

一、说明 一段时间以来&#xff0c;我一直想构建一个运动激活且具有延时功能的树莓派相机&#xff0c;但从未真正找到我喜欢的案例。我在thingiverse上找到了这个适合树莓派和相机的好案例。它是为特定的鱼眼相机设计的&#xff0c;但从模型来看&#xff0c;我拥有的廉价中国鱼…

【基于Python的二手车数据可视化平台的设计与实现】

基于Python的二手车数据可视化平台的设计与实现 前言数据获取与处理网络爬虫数据存储 可视化平台的设计与实现Flask框架数据可视化 创新点结语 前言 随着社会的不断发展&#xff0c;二手车市场也逐渐成为一个备受关注的领域。为了更好地为二手车的买家和卖家提供信息&#xff…

Pycharm设置为中文版

文章目录 关注公众号&#xff1a;『AI学习星球』 算法学习、4对1辅导、论文辅导或核心期刊可以通过公众号或CSDN滴滴我 在使用Pycharm的时候&#xff0c;会发现里面的菜单栏以及内容都是英文为主。 英文版的优点是&#xff1a;比较稳定&#xff0c;其次大家都在用英文版&…

MobaXterm成功连接到开发环境后,过一段时间会自动断开。

问题现象 MobaXterm成功连接到开发环境后&#xff0c;过一段时间会自动断开。 原因 配置MobaXterm工具时&#xff0c;没有勾选“SSH keepalive”或专业版MobaXterm工具的“Stop server after”时间设置太短。

Android 样式小结

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、使用3.1 创建并应用样式3.2 创建并…

zabbix 通过 odbc 监控 mssql

1、环境 操作系统&#xff1a;龙蜥os 8.0 zabbix&#xff1a;6.0 mssql&#xff1a;2012 2、安装odbc 注意&#xff1a;需要在zabbix server 或者 zabbix proxy 安装 odbc驱动程序 dnf -y install unixODBC unixODBC-devel3、安装mssql驱动程序 注意&#xff1a;我最开始尝试…

【Unity】Addressable包资源加载失败:CRC Mismatch.

Error while downloading Asset Bundle: CRC Mismatch. 是资源下载校验失败&#xff0c;但是资源和上次打包的资源是一样的。没有排查到原因&#xff0c;在谷歌搜索后看到 大概就是指Unity版本修改后打包&#xff0c;会破坏原来的CRC信息&#xff0c;导致导报出来的资源无法通…

一篇文章带你了解并使用mybatis框架

mybatis简介&#xff1a; MyBatis 是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff08;P…

深度学习之全面了解预训练模型

在本专栏中&#xff0c;我们将讨论预训练模型。有很多模型可供选择&#xff0c;因此也有很多考虑事项。 这次的专栏与以往稍有不同。我要回答的问题全部源于 MathWorks 社区论坛&#xff08;ww2.mathworks.cn/matlabcentral/&#xff09;的问题。我会首先总结 MATLAB Answers …

Python time模块详解

time 模块主要包含各种提供日期、时间功能的类和函数。该模块既提供了把日期、时间格式化为字符串的功能&#xff0c;也提供了从字符串恢复日期、时间的功能。 在 Python 的交互式解释器中先导入 time 模块&#xff0c;然后输入 [e for e in dir(time) if not e.startswith(_)…

【数据结构】万字一文手把手解读哈希————(开/闭散列)解决哈希冲突完整详解(6)

前言 大家好吖&#xff0c;欢迎来到 YY 滴 数据结构 系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴 数据结构 专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 目录 一.哈希&#xff08…

【智能家居】七、人脸识别 翔云平台编程使用(编译openSSL支持libcurl的https访问、安装SSL依赖库openSSL)

一、翔云 人工智能开放平台 API文档开发示例下载 二、编译openSSL支持libcurl的https访问 安装SSL依赖库openSSL(使用工具wget)libcurl库重新配置&#xff0c;编译&#xff0c;安装运行&#xff08;运行需添加动态库为环境变量&#xff09; 三、编程实现人脸识别 四、Base6…

距离度量(各距离含义)

欧氏距离 在n维空间中两点的真实距离&#xff0c;向量的自然长度 由于欧几里得几何学的关系称为欧氏距离 二维空间两点计算公式&#xff1a; d ( x 1 − x 2 ) 2 ( y 1 − y 2 ) 2 d \sqrt{(x_1 - x_2)^2 (y_1 - y_2)^2} d(x1​−x2​)2(y1​−y2​)2 ​ 三维空间两点计算…