Linux0.11内核源码解析-malloc

news2024/11/26 23:42:49

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);
    引用+1
	bdesc->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.coloradmin.cn/o/1160766.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ajax-axios发送 get请求 或者 发送post请求带有请求体参数

/* axios v0.21.1 | (c) 2020 by Matt Zabriskie */ !function(e,t){"object"typeof exports&&"object"typeof module?module.exportst():"function"typeof define&&define.amd?define([],t):"object"typeof export…

记一次大数据事故@用了很久的虚拟机环境突然不能联网了

记一次大数据事故用了很久的虚拟机环境突然不能联网了 背景 今天打开自己电脑上的虚拟机环境打算练习一下flink&#xff0c;结果发现vmware里虚拟机能正常开机&#xff0c;也能正常进图os&#xff0c;但是就是不能ping通主机&#xff0c;主机也不能ping通虚拟机 探查 1、…

绝缘检测原理和绝缘电阻计算方法

文章目录 简介绝缘检测功能绝缘检测原理绝缘电阻检测的常用方法不平衡电桥法 绝缘电阻绝缘电阻的计算 绝缘检测开启或关闭为什么根据 V1 &#xff1c; V2 或 V1 ≥ V2 判断是上桥臂并入电阻还是下桥臂并入电阻 简介 绝缘检测是判断动力&#xff08;正、负&#xff09;总线与外…

Maven本地配置获取nexus私服的依赖

场景 Nexus-在项目中使用Maven私服&#xff0c;Deploy到私服、上传第三方jar包、在项目中使用私服jar包&#xff1a; Nexus-在项目中使用Maven私服&#xff0c;Deploy到私服、上传第三方jar包、在项目中使用私服jar包_nexus maven-releases 允许deploy-CSDN博客 在上面讲的是…

【6】c++11新特性(稳定性和兼容性)—>Lambda表达式

基本用法 lambda表达式是c最重要也是最常用的特性之一&#xff0c;这是现代编程语言的一个特点&#xff0c;lambda表达式有如下的一些优点&#xff1a; &#xff08;1&#xff09;声明式的编成风格&#xff1a;就地匿名定义目标函数活着函数对象&#xff0c;不需要额外写一个命…

Ubuntu20.04安装CUDA、cuDNN、tensorflow2可行流程(症状:tensorflow2在RTX3090上运行卡住)

最近发现我之前在2080ti上运行好好的代码&#xff0c;结果在3090上运行会卡住很久&#xff0c;而且模型预测结果完全乱掉&#xff0c;于是被迫研究了一天怎么在Ubuntu20.04安装CUDA、cuDNN、tensorflow2。 1.安装CUDA&#xff08;包括CUDA驱动和CUDA toolkit&#xff0c;注意此…

【MySQL】MySQL的安装与配置环境变量(使其在控制台上使用)

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《MySQL》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&a…

删除文件要谨慎!如何在Linux中删除目录或文件

删除目录和文件是任何操作系统中最基本但最重要的功能之一。在Linux中,如果运行的是窗口环境,则可以使用文件管理器应用程序查找和删除文件。也许你是通过SSH远程登录的,或者你的Linux计算机没有安装GUI,或者你想对你要删除的内容有更多的控制权。与Linux中的任何东西一样,…

【微服务 Spring Cloud Alibaba】- Nacos 服务注册中心

目录 1. 什么是注册中心&#xff1f; 1.2 注册中心的作用 2. SpringBoot 整合 Nacos 实现服务注册中心 2.1 将服务注册到 Nacos 2.2 实现消费者 3. 服务列表各个参数的含义、作用以及应用场景 1. 什么是注册中心&#xff1f; 注册中心是微服务架构中的一个重要组件&…

NoSQL数据库以及架构介绍

文章目录 一. 什么是NoSQL&#xff1f;二. NoSQL分类三. NoSQL与关系数据库有什么区别四. NoSQL主要优势和缺点五. NoSQL体系框架 其它相关推荐&#xff1a; 系统架构之微服务架构 系统架构设计之微内核架构 鸿蒙操作系统架构 架构设计之大数据架构&#xff08;Lambda架构、Kap…

Selenium学习(Java + Edge)

Selenium /səˈliːniəm/ 1. 简介 ​ Selenium是一个用于Web应用程序自动化测试工具。Selenium测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样。支持的浏览器包括IE、Mozilla Firefox、Safari、Google Chrome、Opera、Edge等。 ​ 适用于自动化测试&#x…

Linux期末复习——文件I/O编程

Linux系统调用以及用户编程接口 三者关系 系统调用、API以及系统命令之间关系&#xff1a; 什么是文件描述符&#xff1f; 是一个非负整数&#xff0c;索引值 打开或者创建一个文件的时候&#xff0c;内核会向进程返回一个文件描述符 读写文件时&#xff0c;会向函数传递一个文…

ModuleNotFoundError: No module named ‘paddle.fluid.incubate.fleet‘

在使用rocketqa的时候可能会遇到下面的问题&#xff1a; 问题&#xff1a; 解决方法&#xff1a; 这完全是paddlepaddle的问题。 在rocketqa/utils/optimization.py出现下面的语句&#xff0c;这个时候直接把出错的注释掉就可以&#xff0c;因为它完全没有用到。&#xff08;…

Win10奇怪的部分文字乱码问题

1.打开Windows设置的时间和语言 2.打开区域下方的的其他日期、时间和区域设置 3.点击更改日期、时间或数字格式。切换到管理 4.点击更改系统区域设置&#xff0c;取消Beta版&#xff1a;使用Unicode UTF-8提供全球语言支持。 按提示重启电脑即可。

Windows电脑怎么下载桌面便签小工具?

Windows电脑是日常办公中常用的工具&#xff0c;电脑上可以安装许多软件来辅助日常办公&#xff0c;其中桌面便签工具可以为大家记录很多日常办公中的各项工作计划&#xff0c;而且便签软件通常可以悬挂于电脑桌面显示&#xff0c;方便大家一边工作一边查看备忘记录。 谈及Win…

探索网络攻击:ARP断网、ARP欺骗和DNS欺骗实验解析

目录 前言 一、ARP概述 1.1 什么是ARP 1.2 ARP协议的基本功能 1.3 ARP缓存表 1.4 ARP常用命令 二、ARP断网实验 三、ARP欺骗实验 3.1 内网截获图片 3.2 HTTP账户密码获取 四、DNS欺骗实验 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&…

OpenGL ES入门教程(一)编写第一个OpenGL程序

OpenGL ES入门教程&#xff08;一&#xff09;编写第一个OpenGL程序 前言 从本文开始我将参考学习OpenGL ES应用开发实践指南 Android卷 [&#xff08;美&#xff09;KevinBrothaler著]&#xff08;提取码: 394m&#xff09;&#xff0c;并基于自己的理解以更加通俗易懂的方式…

[.NET]桃源网络硬盘 v7.4

桃源网络硬盘是一个以.net进行开发的网络硬盘系统源码。 开发环境&#xff1a;Microsoft.NET Framework SDK 运行要求&#xff1a; Windows 2003及以上版本 或 Windows XP及以上版本&#xff0c;安装 .Net Framework 要求上传目录有写权限 请将其放在虚拟目录或单独的网页空间…

Kubernetes包管理工具Helm简介及使用

文章目录 前言技术积累什么是HelmHelm的核心概念Helm可以解决哪些痛点Helm中文官方文档 Helm安装Helm安装nginx用例写在最后 前言 大家都知道K8S是云原生devops的一大利器&#xff0c;可以直接让我们的中间件、应用服务直接运行在云端&#xff0c;让我们可以只关心自身的业务功…

【Unity】【VR开发疑难】Unity运行就报无法启动XR Plugin

【现象】 连接Link后运行Unity的VR项目Link也无反映&#xff0c;Unity控制台报&#xff1a;无法启动XR Plugin&#xff0c;并说是由于Oculus头盔未连接导致。 【分析】 打开Oculus PC客户端&#xff0c;发现状态是连接正常。重启机器后&#xff0c;提示Oculus没有出于RunTim…