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

顾得泉:个人主页
个人专栏:《Linux操作系统》 《C/C++》 《LeedCode刷题》
键盘敲烂,年薪百万!
一、题目要求
1.采用C语言实现
2.伙伴系统采用free_area[11]数组来组织。要求伙伴内存最小为一个页面,页面大小为4KB,最大为4MB,即1024个页面。描述一个空闲伙伴内存块的数据结构为
struct chunk
{unsigned int power; //内存块大小的2次幂指数,如12,13,...,22unsigned 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系统中实现简易的伙伴系统的分享到这里就结束了,希望本篇文章的分享会对大家的学习带来些许帮助,如果大家有什么问题,欢迎大家在评论区留言~~~
相关文章:
Linux系统---简易伙伴系统
顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、题目要求 1.采用C语言实现 2.伙伴系统采用free_area[11]数组来组织。要求伙伴内存最小为一个页面,页面大小为4KB…...
Redis使用Lua脚本
Lua脚本 redis可以支持lua脚本,可以使用lua脚本来将几个命令整合为一个整体来执行,这样可以使得多个命令原子操作,且可以减少网络开销 Lua的数据类型 Lua是一个动态类型的语言,一个变量可以存储任何类型的值,类型有&am…...
macos安装metal 加速版 pytorch
categories: [Python] tags: Python MacOS 写在前面 试试 m3 的 metal 加速效果如何 Mac computers with Apple silicon or AMD GPUsmacOS 12.3 or laterPython 3.7 or laterXcode command-line tools: xcode-select --install 安装 Python: conda-forge brew install minif…...
【学习笔记】lyndon分解
摘抄自quack的ppt。 这部分和 s a sa sa的关联比较大,可以加深对 s a sa sa的理解。 Part 1 如果字符串 s s s的字典序在 s s s以及 s s s的所有后缀中是最小的,则称 s s s是一个 lyndon \text{lyndon} lyndon串。 lyndon \text{lyndon} lyndon分解&a…...
21、命令执行
文章目录 一、命令执行概述1.1 基本定义1.2 原理1.3 两个条件1.4 命令执行漏洞产生的原因1.5 管道符号和通用命令符 二、远程命令执行2.1 远程命令执行相关函数2.2 远程命令执行漏洞的利用 三、系统命令执行3.1 相关函数3.2 系统命令执行漏洞利用 四、命令执行漏洞防御 一、命令…...
Qexo博客后台管理部署
Qexo博客后台管理部署 个人主页 个人博客 参考文档 https://www.oplog.cn/qexo/本地部署 采用本地Docker部署管理本地Hexo 下载代码包 若无法下载使用科学工具下载到本地在上传到服务器 wget https://github.com/Qexo/Qexo/archive/refs/tags/3.0.1.zip# 解压 unzip Qexo…...
最小生成树prim
最小生成树(三)Prim算法及存储结构_哔哩哔哩_bilibili 311 最小生成树 Prim 算法_哔哩哔哩_bilibili #include <iostream> #include <queue> #include <string> #include <stack> #include <vector> #include <set…...
实用篇 | 一文学会人工智能中API的Flask编写(内含模板)
----------------------- 🎈API 相关直达 🎈-------------------------- 🚀Gradio: 实用篇 | 关于Gradio快速构建人工智能模型实现界面,你想知道的都在这里-CSDN博客 🚀Streamlit :实用篇 | 一文快速构建人工智能前端展…...
Si24R03—低功耗 SOC 芯片(集成RISC-V内核+2.4GHz无线收发器)
Si24R03是一款高度集成的低功耗SOC芯片,其集成了基于RISC-V核的低功耗MCU和工作在2.4GHz ISM频段的无线收发器模块。 MCU模块具有低功耗、Low Pin Count、宽电压工作范围,集成了13/14/15/16位精度的ADC、LVD、UART、SPI、I2C、TIMER、WUP、IWDG、RTC等丰…...
C# Winform 日志系统
目录 一、效果 1.刷新日志效果 2.单独日志的分类 3.保存日志的样式 二、概述 三、日志系统API 1.字段 Debug.IsScrolling Debug.Version Debug.LogMaxLen Debug.LogTitle Debug.IsConsoleShowLog 2.方法 Debug.Log(string) Debug.Log(string, params object[]) …...
【Java 基础】27 XML 解析
文章目录 1.SAX 解析器1)什么是 SAX2)SAX 工作流程初始化实现事件处理类解析 3)示例代码 2.DOM 解析器1)什么是 DOM2)DOM 工作流程初始化解析 XML 文档操作 DOM 树 3)示例代码 总结 在项目开发中࿰…...
地图服务 ArcGIS API for JavaScript基础用法全解析
地图服务 ArcGIS API for JavaScript基础用法全解析 前言 在接触ArcGIS之前,开发web在线地图时用过Leaflet来构建地图应用,作为一个轻量级的开源js库,在我使用下来Leaflet还有易懂易用的API文档,是个很不错的选择。在接触使用Ar…...
docker学习(八、mysql8.2主从复制遇到的问题)
在我配置主从复制的时候,遇到了一直connecting的问题。 起初可能是我ip配置的不对,slave_io_running一直connecting。(我的环境:windows中安装了wsl,是ubuntu环境的,在wsl中装了miniconda,mini…...
React-hook-form-mui(三):表单验证
前言 在上一篇文章中,我们介绍了react-hook-form-mui的基础用法。本文将着重讲解表单验证功能。 react-hook-form-mui提供了丰富的表单验证功能,可以通过validation属性来设置表单验证规则。本文将详细介绍validation的三种实现方法,以及如何…...
【私域运营秘籍】4大用户调研方法,让你轻松掌握用户心理!
我们常说私域运营的核心是用户运营。根据二八法则,20%的超级用户贡献企业80%的利润。因此,企业应该根据用户的价值贡献来有针对性地进行运营。 然而,在实际的私域运营中,我们不仅需要找出贡献价值不同的用户,还可以从…...
2.8寸 ILI9341 TFTLCD 学习移植到STM32F103C8T6
2.8寸 ILI9341 TFTLCD 学习移植到STM32F103C8T6 文章目录 2.8寸 ILI9341 TFTLCD 学习移植到STM32F103C8T6前言第1章 LCD简介1.1 LCD硬件接口介绍 第2章 LCD指令介绍第3章 LCD 8080驱动方式3.1 8080写时序3.2 8080读时序 第4章 LCD 驱动代码部分4.1 修改代码部分4.2 代码工程下载…...
Java利用TCP实现简单的双人聊天
一、创建新项目 首先创建一个新的项目,并命名为聊天。然后创建包,创建两个类,客户端(SocketClient)和服务器端(SocketServer) 二、实现代码 客户端代码: package 聊天; import ja…...
软件压力测试的重要性与用途
在当今数字化的时代,软件已经成为几乎所有行业不可或缺的一部分。随着软件应用规模的增加和用户数量的上升,软件的性能变得尤为关键。为了确保软件在面对高并发和大负载时仍然能够保持稳定性和可靠性,软件压力测试变得至关重要。下面是软件压…...
【数据挖掘】国科大苏桂平老师数据库新技术课程作业 —— 第二次作业
1 设 F { A B → C , B → D , C D → E , C E → G H , G → A } F\{AB\rightarrow C,B\rightarrow D, CD\rightarrow E, CE\rightarrow GH, G\rightarrow A \} F{AB→C,B→D,CD→E,CE→GH,G→A},用推理的方法证明 F ∣ A B → G F\;|AB\rightarrow G F∣AB→…...
Qt + MySQL(简单的增删改查)
Qt编译MySql插件教程 帮助: SQL Programming QSqlDatabase 静态函数 1.drivers(),得到可以使用的数据库驱动名字的集合 [static] QStringList QSqlDatabase::drivers();2.addDatabase(),添加一个数据库实例 [static] QSqlDatabase QSql…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
JDK 17 序列化是怎么回事
如何序列化?其实很简单,就是根据每个类型,用工厂类调用。逐个完成。 没什么漂亮的代码,只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...
客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...
MeshGPT 笔记
[2311.15475] MeshGPT: Generating Triangle Meshes with Decoder-Only Transformers https://library.scholarcy.com/try 真正意义上的AI生成三维模型MESHGPT来袭!_哔哩哔哩_bilibili GitHub - lucidrains/meshgpt-pytorch: Implementation of MeshGPT, SOTA Me…...
