内核和进程的内存管理,内核从buddy到alloc到slab到kmalloc,内核的内核栈和中断处理程序栈,进程的虚拟内存到页表

news2024/11/16 21:25:48

内核中的内存管理

内核把物理页作为内存管理的基本单位,尽管处理器最小寻址单位为字,但是MMU(管理内存并且把虚拟地址转换为物理地址的硬件)通常以页为单位进行处理。

每个物理页面都由一个相应的 struct page 结构来表示,4GB的内存大约有20MB的空间是存储每个物理页的struct page。

struct page {
    unsigned long flags;            // 页面状态标志
    atomic_t _count;                // 页面引用计数
    atomic_t _mapcount;             // 页面映射计数
    unsigned long private;          // 用于私有数据
    struct address_space *mapping;  // 与页面关联的地址空间
    pgoff_t index;                  // 页面在地址空间中的偏移量
    struct list_head lru;           // LRU 链表中的节点
    void *virtual;                  // 虚拟地址
};

通过mapping字段可以获取到与页面关联的地址空间对象,拥有者可以是用户空间进程,动态分配的内核数据,静态内核代码和页高速缓存等。

struct address_space {
    const struct address_space_operations *a_ops;
    struct inode *host; // 关联的对象,通常是 inode 结构,查看 inode 结构以获取文件的详细信息
};

内核把物理页划分为不同的区(zone),只是逻辑上的划分。
将内存划分为区,形成不同的内存池。
在一些体系结构中,有些内存不能DMA(Direct Memory Access).
有三种分区(常见的):

  • ZONE_DMA:可以DMA的内存区域。
  • ZONE_NORMAL:可以正常映射的页。
  • ZONE_HIGHEM:"高位内存“,其中的页不能永久地映射到地址空间。

使用page_struct来管理页

分页子系统(Page Allocator)使用struct page来维护空闲页的列表、管理页面的状态等。在内核的其他部分,比如文件系统、内存映射子系统等,也会使用struct page来管理页面。

伙伴系统(Buddy System)是一种常见的物理内存管理算法。Buddy Allocator用于管理物理页的分配和释放,而Slab Allocator则用于高效管理内核中的对象缓存。

slab系统和buddy系统和分配内存底层函数的关系

在这里插入图片描述

alloc_pages等获得内存的函数是基于buddy系统,而slab系统又是基于分配内存的函数,kmalloc()又是基于slab系统的(使用了一组通用高速缓存)。

伙伴系统(Buddy System):用于内核的物理内存管理

管理物理帧,为了减少碎片。保持块的大小确定,alloc_pages就是使用buddy system,_get_free_pages 函数是基于伙伴系统的实现的。
维持11个链表,代表不同大小的块(页数不同)。

  • 链表 0(大小为 2^0 = 1个页)
  • 链表 1(大小为 2^1 = 2个页)
  • 链表 2(大小为 2^2 = 4个页)
分配内存:

当需要分配一块大小为 2^k 的内存时,伙伴系统首先检查对应大小的内存块链表。如果找到了一个空闲的块,就将其分配出去。
如果对应大小的链表中没有可用的块,系统会向更大一级的链表查找,直到找到一个可用的块。这个找到的块会被一分为二,其中一个分配给请求者,而另一个则继续放入对应大小的链表。

释放内存:

当一块内存被释放时,伙伴系统会检查其相邻的块是否也是空闲的。如果是,它们将被合并成一个更大的块,并将该块插入到对应大小的链表中。
这个过程会一直进行,直到找到一个不是空闲的伙伴块或者达到最大的块大小。
这种方式可以有效地减少外部碎片,因为当内存被释放时,相邻的空闲块很有可能会被合并成一个更大的块,使得更大的内存块变得可用。

需要注意的是,伙伴系统中通常会有多个链表,每个链表对应不同大小的块。

内存分配和释放的函数

内存分配的底层函数

struct page *alloc_pages(gfp_t gfp_mask,unsigned int order);

该函数分配2的order次方个连续的物理页,并返回一个指针,指向第一个page结构体。

alloc_pages函数与伙伴系统紧密相关,因为它通常是由伙伴系统实现的,用于在物理内存中分配一定数量的连续页面。

void *page_address(struct page * page)

将物理页转换为逻辑地址

unsigned long _get_free_pages(gfp_t gft_mask,unsigned int order);

返回一个指针,指向物理页所在的逻辑地址,而不是struct_page

unsigned long get_zeroed_page(unsigned int gfp_mask);

这个函数和_get_free_pages()实现方式相同,只是将分配好的页都填充为了0.

内存释放的底层函数

void _free_pages(struct page* page,unsigned int order)
free_pages(unsigned long addr,unsigned int order);

void free page(unsigned long addr);

以字节为单位的分配和释放:kmalloc()和kfree();vmalloc()和vfree();

void* kmalloc(size_t size,gfp_t flags)

这个函数返回一个指向内存块的指针,其内存块至少要有size大小,所分配的内存区是物理上连续的

gfp_mask标志
行为修饰符标识内核该如何分配所需内存。

void vmalloc(unsigned long size)

返回的内存物理地址上不是连续的,使用较少。

Slab分配器

buddy无法分配字节大小的内存块,slab分配器就应运而生了,专为小内存分配而生。slab分配器分配内存以Byte为单位。但是slab分配器并没有脱离伙伴系统,而是基于伙伴系统分配的大内存进一步细分成小内存分配。

在这里插入图片描述

分配和释放数据结构的缓存链表。
空闲链表(即图中的高速缓存)包含可供使用的,已经分配好的数据结构块,当使用时就从链表中取出一个。
图中的对象指的是固定大小的内存块(即被缓存的数据结构)。
我们可以创建任何数据结构的高速缓存链表。

slab管理的内容

Slab Allocator通常用于管理内核中的对象缓存,其中缓存的对象的大小是固定的。这些对象缓存可以包括一系列常用的内核数据结构,以提高对这些数据结构的分配和释放的效率。以下是一些常见的内核数据结构,通常由Slab Allocator来管理:

进程控制块(Process Control Block,PCB):

每个运行的进程在内核中都有一个对应的 PCB,包含了进程的各种信息,如进程状态、寄存器值、进程ID等。

文件结构体(File Structure):

内核中管理文件的结构体,包含有关文件的信息,如文件描述符、文件位置指针、文件状态等。

网络套接字结构体:

用于表示网络套接字的结构体,包含有关套接字的信息,如协议、端口号、连接状态等。

页表项(Page Table Entry):

用于虚拟内存管理的页表项,包含有关虚拟地址到物理地址的映射信息。

目录项(Directory Entry):

用于文件系统管理的目录项,包含有关文件或子目录的信息,如文件名、文件类型、文件大小等。

缓存块结构体:

用于文件系统缓存的数据块结构体,包含文件数据、索引节点等信息。

内核栈

每个进程的内核栈小而且固定。总的来说,内核栈为一页或者两页。

中断处理程序栈

中断栈为每个进程提供一个用于中断处理程序的栈

用户的内存空间分配

创建进程的虚拟地址空间分配

操作系统会为每个用户进程提供一个虚拟地址空间,这个虚拟地址空间通常是连续的、从0开始的地址范围。具体的大小和布局取决于操作系统和硬件架构。

操作系统会为用户进程的虚拟地址空间建立页表,用于将虚拟地址映射到物理地址。

这个过程涉及到虚拟地址的划分,例如将虚拟地址空间划分为代码段、数据段、栈等不同的区域。

懒加载: 初始时,并不是所有的虚拟地址空间都会被立即映射到物理内存中。部分页面可能是“懒加载”的,只有在访问到相应的虚拟地址时,才会触发实际的物理内存分配和映射。

内存分配: 当用户进程需要分配内存时,通常会使用用户空间的内存分配函数(例如 malloc、calloc、brk、mmap 等),而这些函数会在用户空间实现内存管理。这些函数可能采用不同的算法和数据结构来管理用户空间的堆内存。

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

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

相关文章

打造高效经营:开发连锁餐饮管理系统的技术深度解析

为了适应市场的快速发展和提高经营效率,许多连锁餐饮企业纷纷投入开发连锁餐饮管理系统。 一、数字化转型的动力 传统的餐饮经营面临着诸多挑战,如订单管理、库存控制、人力资源等问题。在这样的背景下,连锁餐饮企业迫切需要一种全面而高效…

jenkins pipeline配置maven可选参数

1、在Manage Jenkins下的Global Tool Configuration下对应的maven项添加我们要用得到的不同版本的maven安装项 2、pipeline文件内容具体如下 我们maven是单一的,所以我们都是配置单选参数 pipeline {agent anyparameters {gitParameter(name: BRANCH_TAG, type: …

【智能家居入门之微信小程序控制下位机】(STM32、ONENET云平台、微信小程序、HTTP协议)

实现微信小程序控制单片机外设动作 一、使用ONENET可视化组件控制单片机外设动作二、使用微信小程序控制单片机外设动作三、总结 本篇博客话接上文: https://blog.csdn.net/m0_71523511/article/details/135892908 上一篇博客实现了微信小程序接收单片机上传的数据…

web wifi配网和模式切换-esp8266和esp32

web wifi配网和模式切换-esp8266和esp32 支持模式:1:tcp client() 2:tcp server 3:http server(POST/GET) 4:http client 5:udp,6:factory,7:mqtt 配网进入方式: 开机,指示灯亮起后(需要灯闪烁3下后),需在3s内(超过3s则会正常启动…

【网络】 WireShark实现TCP三次握手和四次挥手

目录 一、WireShark介绍 二、什么是TCP 三、TCP三次握手 四、TCP四次挥手 一、WireShark介绍 WireShark是一个开源的网络分析工具,用于捕获和分析网络数据包。它可以在多个操作系统上运行,包括Windows、Mac OS和Linux。 使用WireShark,…

获取鼠标点击图片时候的坐标,以及利用html 中的useMap 和area 实现图片固定位置的点击事件

一 编写原因 应项目要求,需要对图片的固定几个位置分别做一个点击事件,响应不同的操作,如下图,需要点击红色区域,弹出不同的提示框: 二 获取点击图片时候的坐标 1. 说明 实现这以上功能的前提是需要确定需…

Kubenetes Ingress 用法

Service的表现形式为IP地址端口号的方式,即工作在TCP/IP层,而对于基于HTTP的服务来说,Service机制很难实现,7层应用的复杂转发逻辑。kubenetes在1.1版本开始引入ingress资源对象,用于将集群外部的客户端请求路由到集群…

STM32与FPGA实现以太网功能--ping

方案: ①stm32与88E6320的一个RMII接口连接,实现网管功能。 ②FPGA与88E6320的另一个RMII接口连接,使用UDP实现业务数据传输。 ③stm32与FPGA中MAC地址不同,但是IP使用相同 结果: 1、在局域网点对点通信正常。 2…

最优化基础 - (最优化问题分类、凸集)

系统学习最优化理论 什么是最优化问题? 决策问题: (1)决策变量 (2)目标函数(一个或多个) (3)一个可由可行策略组成的集合(等式约束或者不等式约束…

Go语言中HTTP代理的请求和响应过程

在Go语言中,HTTP代理的实现涉及对请求和响应的拦截、转发和处理。下面将详细介绍这个过程。 请求过程: 客户端发起请求:客户端(例如浏览器或其他应用程序)发送HTTP请求到代理服务器。建立连接:代理服务器…

第九节HarmonyOS 常用基础组件14-DataPanel

1、描述 数据面板组件,用于将多个数据占比情况使用占比图进行展示。 2、接口 DataPanel(options:{values: number[], max?: numner, type?: DataPanelType}) 3、参数 参数名 参数类型 必填 描述 values number[] 是 数据值列表,最多含9条数…

vue3 el-pagination 将组件中英文‘goto’ 修改 为 中文到‘第几’

效果如图&#xff1a; 要求&#xff1a;将英文中Go to 改为到第几 操作如下&#xff1a; <template><div class"paging"><el-config-provider :locale"zhCn"> // 注意&#xff1a;这是重要部分<el-pagination //分页组件根据官…

需维护的钢对钢和钢对铜滑动接触表面组合的基本额定寿命计算

以下公式仅限用于计算初始润滑的基本额定寿命 Gh b1 b2 b3 b4 b5 330 / p2,5 v 当轴承在初次润滑后能够定期补充润滑&#xff0c;可以用下列公式计算寿命 GhN Gh fβ fH 或 GN 60 f GhN 补充润滑频率可用下列公式进行计算 H Gh / N 其中 Gh 只进行初次润滑条件下的…

Java中实例化的一般过程

在Java中&#xff0c;当你有几个类&#xff08;如 ManualTriggerStartNode, EndNode, TimerTriggerStartNode&#xff09;继承自一个基类&#xff08;如 BaseNode&#xff09;&#xff0c;实例化这些子类时的确定性主要依赖于你的具体需求和上下文。 实例化的一般过程&#xf…

什么是图形组态软件?可视化组态工具的特点

组态软件的定义 组态软件主要作为SCADA系统及其他控制系统的上位机人机界面的开发平台&#xff0c;为用户提供快速地构建工业自动化系统数据采集和实时监控功能服务。它使用灵活的组态方式&#xff0c;提供快速构建工业自动控制系统监控功能的通用层次的软件工具。 组态软件的…

GPT栏目:yarn 安装

GPT栏目&#xff1a;yarn 安装 一、前言 在跟GPT交互的时候&#xff0c;发现最近gpt4给出的答案率有了比较明显的提高&#xff0c;简单记录一下&#xff0c;我用gpt4拿到的答案吧。 本人已按照这个步骤成功 二、具体步骤 要安装 yarn&#xff0c;你可以按照以下步骤进行操作…

《Linux C编程实战》笔记:管道

从这节开始涉及进程间的通信&#xff0c;本节是管道。 管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性&#xff0c;管道又称之为半双工管道。。管道的这一特点决定了其使用的局限性。 数据只能由一个进程刘翔另一个进程&#xff1b;如果要进行全双工通信…

2024 IC FPGA 岗位 校招面试记录

引言 各位看到这篇文章时&#xff0c;24届校招招聘已经渐进尾声了。 在这里记录一下自己所有面试&#xff08;除了时间过短或者没啥干货的一些研究所外&#xff0c;如中电55所&#xff08;南京&#xff09;&#xff0c;航天804所&#xff08;上海&#xff09;&#xff09;的经…

如何“安装CyberDuck和使用”win11系统?

1、下载 下载 (cyberduck.io) 2、安装 3、使用

【SpringBoot3】集成Knife4j、springdoc-openapi作为接口文档

一、什么是springdoc-openapi Springdoc-openapi 是一个用于生成 OpenAPI&#xff08;之前称为 Swagger&#xff09;文档的库&#xff0c;专为 Spring Boot 应用程序设计。它可以根据你的 Spring MVC 控制器、REST 控制器和其他 Spring Bean 自动生成 OpenAPI 文档&#xff0c…