Linux0.11内核源码解析-malloc

malloc介绍

Linux内核版本0.11中的`malloc.c`文件实现了内存分配的功能。在这个版本的Linux内核中,`malloc.c`文件包含了内核级别的内存分配函数,用于分配和释放内核中的内存。这些函数可以帮助内核管理可用的内存,并允许内核动态地分配和释放内存,以便在运行时满足不同模块或进程的内存需求。基本上,它实现了类似C标准库中的`malloc()`和`free()`函数的功能,但是是针对内核级别的操作而设计的。

C标准库和内核中malloc区别

为了加以区分后面malloc命名为kmalloc,free命名为kfree

C标准库中的`malloc`函数和内核中的`malloc`函数之间存在一些关键区别:

1. **作用域不同**:C标准库中的`malloc`函数是用于用户空间程序的内存分配,而内核中的`malloc`函数是用于操作系统内核的内存管理。

2. **权限不同**:C标准库中的`malloc`函数只能操作用户空间的内存,而内核中的`malloc`函数可以直接操作系统的内存,包括内核空间的内存。

3. **实现不同**:C标准库中的`malloc`函数通常基于用户空间的堆实现,而内核中的`malloc`函数是基于内核空间的内存管理机制实现的,因此更加底层且复杂。

4. **用途不同**:C标准库中的`malloc`函数主要用于用户空间程序的动态内存分配,而内核中的`malloc`函数用于操作系统内核的动态内存分配,包括内核数据结构和缓冲区的分配。

bucket分配算法

Bucket(桶)内存分配算法是一种用于管理动态内存分配的方法,通常应用于用户空间的内存分配库。这种算法基于固定大小的内存块(或桶),每个桶大小相同,并且事先确定。这些桶可以是不同大小的内存块,以适应不同大小的内存需求。

其基本思想是将内存空间分割成预定义大小的桶(或块),例如8字节、16字节、32字节等。当程序请求分配一定大小的内存时,分配器会根据请求大小找到合适大小的桶,然后从这个桶中分配内存。如果某个桶中没有足够大小的内存可用,它会尝试从较大的桶中拆分出适当大小的内存块来满足请求。

这种算法的优点在于:

1. **降低内存碎片化**:通过使用预定义大小的桶,可以减少内存碎片化,因为每个桶大小是固定的,不会出现零散的小内存碎片。

2. **快速分配**:由于预定义了多个固定大小的桶,分配器只需根据请求大小找到对应的桶,因此分配速度相对较快。

不过,Bucket内存分配算法也有一些限制:

1. **内存浪费**:当需要的内存大小不完全匹配桶的大小时,可能会导致一定程度的内存浪费。

2. **固定桶大小**:由于每个桶大小是固定的,可能难以适应特定大小的内存需求。

结构体介绍

`struct bucket_desc`表示一个桶的描述符,包含以下字段:

- `void *page`:指向桶的起始地址。
- `struct bucket_desc *next`:指向下一个桶的描述符,用于构建链表。
- `void *freeptr`:指向桶中空闲内存的起始地址。
- `unsigned short refcnt`:引用计数,用于跟踪桶的使用情况。
- `unsigned short bucket_size`:桶的大小,表示每个桶可以分配的内存块大小。

`struct _bucket_dir`表示桶的目录,包含以下字段:

- `int size`:桶的目录大小,表示桶的数量。
- `struct bucket_desc *chain`:指向桶链表的头部,用于管理所有桶的分配情况。

这些结构体的设计是为了实现Bucket内存分配算法的核心功能。通过`struct bucket_desc`中的链表和引用计数,可以跟踪和管理每个桶的使用情况。而`struct _bucket_dir`中的链表头部和目录大小,可以帮助定位和管理所有桶的分配情况。

struct bucket_desc {	/* 16 bytes */void			*page;struct bucket_desc	*next;void			*freeptr;unsigned short		refcnt;unsigned short		bucket_size;
};struct _bucket_dir {	/* 8 bytes */int			size;struct bucket_desc	*chain;
};struct _bucket_dir bucket_dir[] = {{ 16,	(struct bucket_desc *) 0},{ 32,	(struct bucket_desc *) 0},{ 64,	(struct bucket_desc *) 0},{ 128,	(struct bucket_desc *) 0},{ 256,	(struct bucket_desc *) 0},{ 512,	(struct bucket_desc *) 0},{ 1024,	(struct bucket_desc *) 0},{ 2048, (struct bucket_desc *) 0},{ 4096, (struct bucket_desc *) 0},{ 0,    (struct bucket_desc *) 0}};   /* End of list marker *//** This contains a linked list of free bucket descriptor blocks*/
struct bucket_desc *free_bucket_desc = (struct bucket_desc *) 0;

空闲存储桶

bucket结构体初始化

初始化桶描述符,建立空闲桶描述符链表

/** This routine initializes a bucket description page.*/
static inline void init_bucket_desc()
{struct bucket_desc *bdesc, *first;int	i;申请一页内存first = bdesc = (struct bucket_desc *) get_free_page();if (!bdesc)panic("Out of memory in init_bucket_desc()");计算一页内存可存放桶描述符数量for (i = PAGE_SIZE/sizeof(struct bucket_desc); i > 1; i--) {bdesc->next = bdesc+1;bdesc++;}/** This is done last, to avoid race conditions in case * get_free_page() sleeps and this routine gets called again....*/将空闲桶描述指针加入链表bdesc->next = free_bucket_desc;free_bucket_desc = first;
}

malloc函数

分配动态内存函数

void *malloc(unsigned int len)
{struct _bucket_dir	*bdir;struct bucket_desc	*bdesc;void			*retval;/** First we search the bucket_dir to find the right bucket change* for this request.*/找到合适的桶for (bdir = bucket_dir; bdir->size; bdir++)if (bdir->size >= len)break;if (!bdir->size) {printk("malloc called with impossibly large argument (%d)\n",len);panic("malloc: bad arg");}/** Now we search for a bucket descriptor which has free space*/cli();	/* Avoid race conditions */寻找对应的桶空闲空间的桶描述符for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) if (bdesc->freeptr)break;/** If we didn't find a bucket with free space, then we'll * allocate a new one.*/if (!bdesc) {char		*cp;int		i;if (!free_bucket_desc)	init_bucket_desc();bdesc = free_bucket_desc;free_bucket_desc = bdesc->next;bdesc->refcnt = 0;bdesc->bucket_size = bdir->size;bdesc->page = bdesc->freeptr = (void *) (cp = get_free_page());if (!cp)panic("Out of memory in kernel malloc()");/* Set up the chain of free objects */for (i=PAGE_SIZE/bdir->size; i > 1; i--) {*((char **) cp) = cp + bdir->size;cp += bdir->size;}*((char **) cp) = 0;bdesc->next = bdir->chain; /* OK, link it in! */bdir->chain = bdesc;}返回指针即等于该描述符对应页面的当前空闲指针retval = (void *) bdesc->freeptr;调整空闲指针指向下一个对象bdesc->freeptr = *((void **) retval);引用+1bdesc->refcnt++;开发中断sti();	/* OK, we're safe again */return(retval);
}

free释放内存

/** Here is the free routine.  If you know the size of the object that you* are freeing, then free_s() will use that information to speed up the* search for the bucket descriptor.* * We will #define a macro so that "free(x)" is becomes "free_s(x, 0)"*/
void free_s(void *obj, int size)
{void		*page;struct _bucket_dir	*bdir;struct bucket_desc	*bdesc, *prev;bdesc = prev = 0;/* Calculate what page this object lives in */page = (void *)  ((unsigned long) obj & 0xfffff000);/* Now search the buckets looking for that page */for (bdir = bucket_dir; bdir->size; bdir++) {prev = 0;/* If size is zero then this conditional is always false */if (bdir->size < size)continue;for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next) {if (bdesc->page == page) goto found;prev = bdesc;}}panic("Bad address passed to kernel free_s()");
found:cli(); /* To avoid race conditions */*((void **)obj) = bdesc->freeptr;bdesc->freeptr = obj;bdesc->refcnt--;if (bdesc->refcnt == 0) {/** We need to make sure that prev is still accurate.  It* may not be, if someone rudely interrupted us....*/if ((prev && (prev->next != bdesc)) ||(!prev && (bdir->chain != bdesc)))for (prev = bdir->chain; prev; prev = prev->next)if (prev->next == bdesc)break;if (prev)prev->next = bdesc->next;else {if (bdir->chain != bdesc)panic("malloc bucket chains corrupted");bdir->chain = bdesc->next;}free_page((unsigned long) bdesc->page);bdesc->next = free_bucket_desc;free_bucket_desc = bdesc;}sti();return;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

投资者如何保障个人利益?行业律师与欧科云链专家给出建议

香港作为全球加速拥抱Web3变革的引领之地&#xff0c;规定自今年6月起在香港经营虚拟资产服务业务需申领牌照。蜂拥而至的Web3创业公司&#xff0c;伺机而动的加密货币交易所&#xff0c;以及跃跃欲试的行业从业者&#xff0c;都让这座金融之都热闹非凡。但近期伴随JPEX诈骗案等…

基于单片机设计的电子柜锁

一、前言 随着现代社会的不断发展&#xff0c;电子柜锁的应用越来越广泛。传统的机械柜锁存在一些不便之处&#xff0c;例如钥匙容易丢失、密码容易泄露等问题。设计一款基于单片机的电子柜锁系统成为了一个有趣而有意义的项目。 该电子柜锁系统通过电磁锁作为柜锁的开关&…

【强化学习】14 —— A3C(Asynchronous Advantage Actor Critic)

A3C算法&#xff08; Asynchronous Methods for Deep Reinforcement Learning&#xff09;于2016年被谷歌DeepMind团队提出。A3C是一种非常有效的深度强化学习算法&#xff0c;在围棋、星际争霸等复杂任务上已经取得了很好的效果。接下来&#xff0c;我们先从A3C的名称入手&…

电脑如何录制小视频

如果你想在你的电脑上录制视频分享给你的朋友或者亲人&#xff0c;无论你的电脑是win还是mac&#xff0c;都可以在本篇文章中找到电脑录制视频的详细教程。小编为你们整理了2种不同系统电脑的录制详细流程&#xff0c;继续阅读查看吧&#xff01; 第一部分&#xff1a;windows…

计算样本方差和总体方差

例如&#xff0c;给出了三个数据&#xff0c;194、183、175&#xff0c;现在计算样本方差和总体方差。 手工计算 它们的平均值 样本方差 总体方差 用excel计算 样本方差 总体方差

ChatGPT对未来发展的影响?一般什么时候用到GPT

ChatGPT以其强大的自然语言处理能力对未来的发展具有重要影响。以下是ChatGPT的潜在影响和一般使用情况&#xff1a; 改善自然语言理解和生成&#xff1a;ChatGPT和类似的模型可以改善机器对人类语言的理解和生成。这将有助于改进各种应用领域&#xff0c;包括智能助手、聊天机…

恒驰服务 | 华为云数据使能专家服务offering之大数据建设

恒驰大数据服务主要针对客户在进行智能数据迁移的过程中&#xff0c;存在业务停机、数据丢失、迁移周期紧张、运维成本高等问题&#xff0c;通过为客户提供迁移调研、方案设计、迁移实施、迁移验收等服务内容&#xff0c;支撑客户实现快速稳定上云&#xff0c;有效降低时间成本…

基于深度学习的中文情感分类 - 卷积神经网络 情感分类 情感分析 情感识别 评论情感分类 计算机竞赛

文章目录 1 前言2 情感文本分类2.1 参考论文2.2 输入层2.3 第一层卷积层&#xff1a;2.4 池化层&#xff1a;2.5 全连接softmax层&#xff1a;2.6 训练方案 3 实现3.1 sentence部分3.2 filters部分3.3 featuremaps部分3.4 1max部分3.5 concat1max部分3.6 关键代码 4 实现效果4.…

【TES720D】青翼科技基于复旦微的FMQL20S400全国产化ARM核心模

板卡概述 TES720D是一款基于上海复旦微电子FMQL20S400的全国产化核心模块。该核心模块将复旦微的FMQL20S400&#xff08;兼容FMQL10S400&#xff09;的最小系统集成在了一个50*70mm的核心板上&#xff0c;可以作为一个核心模块&#xff0c;进行功能性扩展&#xff0c;特别是用…

chat gpt 在开发当中的应用

chatgpt 出来已经有一段时间了&#xff0c;本人在开发的过程中也是有去使用。 经常使用的是讯飞大模型和通义千问&#xff0c;在使用的过程中&#xff0c;个人感觉讯飞大模型在写代码方面会比较智能。 比如问一个 sqlser 单表 数据量 几个亿如何处理的问题&#xff0c;讯飞会给…

CH09_重新组织数据

拆分变量&#xff08;Split Variable&#xff09; 曾用名&#xff1a;移除对参数的赋值&#xff08;Remove Assignments to Parameters&#xff09; 曾用名&#xff1a;分解临时变量&#xff08;Split Temp&#xff09; let temp 2 * (height width); console.log(temp); t…

浅析Redis大Key | 京东云技术团队

一、背景 在京东到家购物车系统中&#xff0c;用户基于门店能够对商品进行加车操作。用户与门店商品使用Redis的Hash类型存储&#xff0c;如下代码块所示。不知细心的你有没有发现&#xff0c;如果单门店加车商品过多&#xff0c;或者门店过多时&#xff0c;此Key就会越来越大…

SpringMVC Day 08 : 文件上传下载

前言 文件上传和下载是 Web 开发中的重要环节&#xff0c;但它们往往不那么容易实现。幸运的是&#xff0c;Spring MVC 提供了一套简单而又强大的解决方案&#xff0c;让我们可以专注于业务逻辑&#xff0c;而不必过多关注底层的文件处理细节。 在本篇博客中&#xff0c;我们…

UE5——网络——RPC

RPC&#xff08;这个是官方文档的资料&#xff09; 要将一个函数声明为 RPC&#xff0c;您只需将 Server、Client 或 NetMulticast 关键字添加到 UFUNCTION 声明。 例如&#xff0c;若要将某个函数声明为一个要在服务器上调用、但需要在客户端上执行的 RPC&#xff0c;您可以…

在Maven中发布项目到Nexus私有服务器

一、测试环境 Sonatype Nexus 3.61.0-02 Maven 3.9.2 二、环境配置 2.1找到maven的配置文件 2.2添加私有仓库账户密码 <servers><server><id>nexus</id><username>admin</username><password>admin</password></server&…

【Linux】Linux+Nginx部署项目(负载均衡动静分离)

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Linux的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Nginx负载均衡 1.什么是负载均衡 2.实…

网站如何改成HTTPS访问

在今天的互联网环境中&#xff0c;将网站更改成HTTPS访问已经成为了一种标准做法。HTTPS不仅有助于提高网站的安全性&#xff0c;还可以提高搜索引擎排名&#xff0c;并增强用户信任。因此&#xff0c;转换为HTTPS是一个重要的举措&#xff0c;无论您拥有个人博客、电子商务网站…

年度评选开启,边缘力量驱动科技未来!

随着人工智能技术的快速发展&#xff0c;边缘计算作为一种新兴技术&#xff0c;正逐渐成为实现智能制造、智慧城市、自动驾驶等领域的关键技术之一。边缘计算能够在靠近数据源的地方进行数据处理和分析&#xff0c;从而提高数据的实时性和可靠性&#xff0c;同时降低网络带宽和…

【Linux】jdk Tomcat MySql的安装及Linux后端接口部署

一&#xff0c;jdk安装 1.1 上传安装包到服务器 打开MobaXterm通过Linux地址连接到Linux并登入Linux&#xff0c;再将主机中的配置文件复制到MobaXterm 使用命令查看&#xff1a;ll 1.2 解压对应的安装包 解压jdk 解压命令&#xff1a;tar -xvf jdk 加键盘中Tab键即可…

【LVS实战】02 搭建一个LVS-NAT模式实验

一、网络结构 用虚拟机搭建如下的几台机器&#xff0c;并配置如下的ip 关于虚拟机网卡和网络的配置&#xff0c;可以参考 iptables章节&#xff0c;05节&#xff1a;网络转发实验 主机A模拟外网的机器 B为负载均衡的机器 C和D为 RealServer 二、C和D主机的网关设置 C和D机…