当前位置: 首页 > news >正文

[Linux内核驱动]内存动态申请

内核空间内存动态申请

更多详细内容可以查看我的github

kmalloc()

函数原型:

void *kmalloc(size_t size, gfp_t flags);

参数说明:

  • size:要分配的内存块的大小,以字节为单位。
  • flags:分配标志,用于指定内存分配的策略和属性。
    • GFP_KERNEL:在内核空间的进程中分配内存
    • GFP_ATOMIC:在原子上下文中分配内存

kmalloc()的底层依赖于__get_free_page()来实现,当使用 GFP_KERNEL 申请内存时,若暂时不能满足,则进程会睡眠等待页,引起阻塞,因此不能在 中断上下文 或持有 自选锁 的时候使用GFP_KERNEL申请内存。对于这些在非进程上下文中不能阻塞的情况,应当使用GFP_ATOMIC申请内存,若不存在空闲页,则不等待,直接返回。

kmalloc()类似,kzalloc() 函数也用于分配内存,区别在于kzalloc()函数会在分配的内存块中清零。

kmalloc()kzalloc()申请的内存都使用 kfree() 函数释放

__get_free_pages()

__get_free_pages()系列函数/宏本质上是Linux内核最底层用户获取空闲内存的方法。因为底层的buddy算法以2n页的方式管理内存,所以底层申请内存是以2n页为单位。n最大为10或11

  • __get_free_pages(gfp_mask, int order):分配2^order页的内存。
  • __get_free_page(gfp_mask):分配一个页(4KB)的内存。
    • 这个宏实际上就是调用__get_free_pages分配1页内存
  • get_zeroed_page(gfp_mask):分配并清零一个页的内存。

在可能阻塞的上下文中(如进程上下文),应使用允许阻塞的标志(GFP_KERNEL)。在不允许阻塞的上下文中(如中断上下文或持有自旋锁时),应使用不允许阻塞的标志(GFP_ATOMICGFP_NOWAIT)。

上面的申请的内存使用free_page(addr)free_pages(addr, order)释放。

vmalloc()

vmalloc()函数用于在内核中分配大的、连续的虚拟地址空间,但物理地址可能不连续。这通常用于需要连续虚拟地址但不需要物理连续性的情况,如大型数据结构或设备驱动程序的缓冲区。vmalloc()需要建立新的页表项,所以其开销很大。此外,vmalloc()不能应用在原子上下文中,因为其内部实现使用了GFP_KERNEL标志的kmalloc()

函数原型:

void *vmalloc(unsigned long size);
void vfree(void *addr);

slab分配器

在Linux中,伙伴分配器(buddy allocator)是以页为单位管理和分配内存。但在内核中的需求,一方面,完全使用页为单位申请内存严重浪费内存;另一方面,Linux运行过程中经常会涉及到大量重复对象的重复生成、使用和释放内存问题(task_struct、inode等)。

为了解决这个问题,Linux内核引入了slab分配器。slab分配器以字节为单位,从 Buddy 分配器中申请内存,之后对申请来的内存细分管理。

struct kmem_cache

struct kmem_cache:这是Slab分配器的一部分,它提供了一种用于快速分配和释放固定大小内存块的机制。Slab分配器为每种大小的对象维护一个缓存池,从而提高了内存分配的效率。

kmem_cache_create()

创建一个新的kmem_cache实例。

函数原型:

struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *));

参数说明:

  • name: 缓存的名称,用于调试和日志记录。
  • size: 缓存中每个对象的大小(以字节为单位)。
  • align: 每个对象的对齐要求(通常设置为0,让slab分配器选择最佳的对齐)。
  • flags: 标志位,用于控制缓存的行为
    • SLAB_HWCACHE_ALIGN:表示对象应该按硬件缓存行对齐,即对齐到一个缓存行
    • SLAB_RECLAIM_DMA:表示在DMA区域中分配
  • ctor: 构造函数(可选),当从缓存中分配对象时,此函数将被调用以初始化对象。

返回值:

  • 成功时返回一个指向新创建的 kmem_cache 结构体的指针。
  • 失败时返回 NULL。

kmem_cache_alloc()

从指定的kmem_cache中分配内存

函数原型:

c
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags);

参数说明:

  • cachep: 之前通过 kmem_cache_create() 创建的 kmem_cache 结构体的指针。
  • flags: GFP(Get Free Pages)标志,用于控制内存分配的行为。

返回值:

  • 成功时返回一个指向新分配对象的指针。
  • 失败时(例如,由于内存不足)返回 NULL。

kmem_cache_free()

释放kmem_cache_alloc申请的内存

函数原型:

void kmem_cache_free(struct kmem_cache *cachep, void *objp);

参数说明:

  • cachep: 与对象关联的 kmem_cache 结构体的指针。
  • objp: 要释放的对象的指针。

kmem_cache_destroy()

销毁一个kmem_cache实例。

函数原型:

void kmem_cache_destroy(struct kmem_cache *cachep);

代码

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/gfp.h>
#include <linux/vmalloc.h>struct mem_dev
{char* test;struct kmem_cache* cache;
};struct mem_dev* mem_devp;static int __init mem_dev_init_module(void)
{printk(KERN_INFO "mem_init\n");mem_devp = kmalloc(sizeof(struct mem_dev), GFP_KERNEL);// kmallocmem_devp->test = kmalloc(1024, GFP_KERNEL);if (!mem_devp->test){return -ENOMEM;}printk(KERN_INFO "kmalloc get addr %p\n", mem_devp->test);kfree(mem_devp->test);// __get_free_pagemem_devp->test = (void*)__get_free_page(GFP_KERNEL);if (!mem_devp->test){return -ENOMEM;}printk(KERN_INFO "__get_free_page get addr %p\n", mem_devp->test);free_page((unsigned long)mem_devp->test);// vmallocmem_devp->test = vmalloc(PAGE_SIZE * 16);if (!mem_devp->test){return -ENOMEM;}printk(KERN_INFO "vmalloc get addr %p\n", mem_devp->test);vfree(mem_devp->test);// slabmem_devp->cache = kmem_cache_create("mem_cache", sizeof(struct mem_dev), 0, SLAB_HWCACHE_ALIGN, NULL);if (!mem_devp->cache){return -ENOMEM;}mem_devp->test = kmem_cache_alloc(mem_devp->cache, GFP_KERNEL);if (!mem_devp->test){return -ENOMEM;}printk(KERN_INFO "slab get addr %p\n", mem_devp->test);kmem_cache_free(mem_devp->cache, mem_devp->test);kmem_cache_destroy(mem_devp->cache);kfree(mem_devp);return 0;
}static void mem_dev_exit_module(void)
{printk(KERN_INFO "mem_dev exit\n");
}module_init(mem_dev_init_module);
module_exit(mem_dev_exit_module);MODULE_AUTHOR("lidonghang-02");
MODULE_LICENSE("GPL");

相关文章:

[Linux内核驱动]内存动态申请

内核空间内存动态申请 更多详细内容可以查看我的github kmalloc() 函数原型&#xff1a; void *kmalloc(size_t size, gfp_t flags);参数说明&#xff1a; size&#xff1a;要分配的内存块的大小&#xff0c;以字节为单位。flags&#xff1a;分配标志&#xff0c;用于指定内…...

在Worpress增加网站的二级目录,并转向到站外网站

在WordPress中&#xff0c;你可以通过添加自定义重定向来实现将某个二级目录&#xff08;例如 www.example.com/subdir&#xff09;重定向到站外网站。可以通过以下几种方法来实现&#xff1a; 方法一&#xff1a;使用 .htaccess 文件 如果你的服务器使用Apache&#xff0c;你…...

torch.max函数

torch.max函数的用法 第一种第二种 官方介绍&#xff1a;Link 有两种使用场景&#xff0c;输入的参数不同以及返回值不同&#xff1a; 第一种 没有参数dim&#xff0c;但这种只适合一维张量。 torch.max(input) → Tensor Returns the maximum value of all elements in the…...

“打造智能售货机系统,基于ruoyi微服务版本开源项目“

目录 # 开篇 售货机术语 1. 表设计说明 2. 页面展示 2.1 区域管理页面 2.2 合作商管理页面 2.3 点位管理页面 3. 建表资源 3.1 创建表的 SQL 语句&#xff08;包含字段备注&#xff09; 1. Region 表 2. Node 表 3. Partner 表 4. 创建 tb_vending_machine 表的 S…...

LeetCode347:前K个高频元素

题目描述 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 解题思想 使用优先队列 priority_queue<Type, Container, Functional> Type 就是数据类型&#xff0c;Container 就是容器类型&#xff08;C…...

2.线上论坛项目

一、项目介绍 线上论坛 相关技术&#xff1a;SpringBootSpringMvcMybatisMysqlSwagger项目简介&#xff1a;本项目是一个功能丰富的线上论坛&#xff0c;用户可编辑、发布、删除帖子&#xff0c;并评论、点赞。帖子按版块分类&#xff0c;方便查找。同时&#xff0c;用户可以…...

Java面试题:讨论synchronized关键字和java.util.concurrent包中的同步工具,如Lock和Semaphore

在 Java 中&#xff0c;synchronized 关键字和 java.util.concurrent 包中的同步工具都是用来控制多线程环境下的并发访问&#xff0c;以防止数据竞争和确保线程安全。下面是对 synchronized 关键字和 java.util.concurrent 包中的一些同步工具的讨论&#xff0c;包括它们的特点…...

酱香型白酒派系介绍

酱香型白酒作为中国传统白酒的重要流派&#xff0c;以其独特的酱香和复杂的酿造工艺而著称。在酱香型白酒中&#xff0c;形成了多个派系&#xff0c;各具特色。 以下是关于北派、茅派、川派和黔派等各个派系的详细介绍。 一、北派 地理位置&#xff1a;主要产于秦岭和淮河以…...

编译chamfer3D报错

python setup.py install编译chamfer3D报错 出现nvcc fatal : Unsupported gpu architecture ‘compute_86‘的问题&#xff0c;是因为显卡与cuda版本支持的算力不匹配。 nvcc fatal : Unsupported gpu architecture ‘compute_86’ ninja: build stopped: subcommand failed. …...

BuildConfig类找不到,BuildConfig.java类不在编译加载路径问题解决

今天用buildConfigField设置编译时常量遇到了问题&#xff0c;访问不到BuildConfig类&#xff0c;import导包也找不到类&#xff0c;具体设置如下&#xff1a; defaultConfig {applicationId com.sample.abcminSdk 28targetSdk 33versionCode getVerInt()//1versionName getVer…...

海外版coze前端代码助手

定位 解决前端同事的开发问题 参数配置 测试 支持 最屌的大模型及语音播报。 体验地址 海外版前端代码助手 需要魔法才能体验油...

python pyautogui实现图片识别点击失败后重试

安装库 pip install Pillow pip install opencv-python confidence作用 confidence 参数是用于指定图像匹配的信度&#xff08;或置信度&#xff09;的&#xff0c;它表示图像匹配的准确程度。这个参数的值在 0 到 1 之间&#xff0c;数值越高表示匹配的要求越严格。 具体来…...

怎么看电脑实时充电功率

因为我想测试不同的充电器给电脑充电的速度&#xff0c;所以就想找一款软件可以看电脑当前充电功率的软件&#xff0c;我给一个图 直接搜索就可以下载了&#xff0c;charge rate就是功率&#xff0c;这里是毫瓦&#xff0c;换算单位是 1000mw1w 所以我这里充电功率是65w&…...

Qt 实战(4)信号与槽 | 4.2、自定义信号与槽

文章目录 一、自定义信号与槽1、自定义信号2、自定义槽3、连接信号与槽4、总结 前言&#xff1a; 在Qt框架中&#xff0c;信号&#xff08;signals&#xff09;和槽&#xff08;slots&#xff09;机制是对象间通信的核心。这种机制允许对象在特定事件发生时发出信号&#xff0c…...

Android开发系列(六)Jetpack Compose之Box

Box是一个用来组合和控制子元素布局的组件。它可以在一个矩形区域内排列一个或多个子元素&#xff0c;并根据所提供的参数来控制它们的位置、大小和样式。 Box的功能类似传统的FrameLayout。 下面通过示例了解Box的使用方法&#xff0c;首先看一个最简单的示例&#xff0c;如下…...

51单片机STC89C52RC——4.1 独立按键(数码管显示按键值)

目录 目录 目的 一&#xff0c;STC单片机模块 二&#xff0c;矩阵按键模块 2.1 针脚定义 ​编辑 2.2 矩阵按键位置 2.3 如何理解按键按下后针脚的高低电平 2.3.1 错误理解1 2.3.2 错误理解2 2.3.3 正确判定按下的是那个按键的逻辑 2.3.4 判定按键按下的依次扫描程…...

解决双击bootstrap.bat没有生成b2.exe文件

双击bootstrap.bat但是并没有没有生成b2.exe文件&#xff0c;会报如下错误&#xff1a; "cl" 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。D:\cppsoft\boost_1_85_0\tools\build\src\engine>dir *.exe 驱动器 D 中的卷是 Data 卷的序列号是…...

AI穿戴设备是未来手机的终结者?中国AI商业化的未来预测

AI技术的发展正处于商业化应用的关键阶段&#xff0c;而中国在互联网时代已凭借商业化应用逆袭。AI算法大模型虽强大&#xff0c;但真正普惠民众需与设备深度结合。穿戴式智能设备就成为了新战场&#xff0c;AI算法与穿戴设备结合能释放更大工作效率。私人助理AI将成趋势&#…...

FPGA+Nvidia Orin NX+AI 异构视频图像处理开发平台在高端医疗和工业检测的应用,支持定制,支持国产化

FPGAGPU 异构架构视频图像处理开发平台&#xff0c;它结合了 AMD Zynq UltraScale MPSoC&#xff08;FPGA&#xff09;与 NVIDIA Jetson Orin NX&#xff08;GPU&#xff09;的强大功能&#xff0c;能够应用于对图像精准度和实时性有着严苛要求的行业领域。 Zynq UltraScale MP…...

2000-2023年各省名义GDP、实际GDP、GDP平减指数数据(含原始数据+计算过程+计算结果)(以2000年为基期)

2000-2023年各省名义GDP、实际GDP、GDP平减指数数据&#xff08;含原始数据计算过程计算结果&#xff09;&#xff08;以2000年为基期&#xff09; 1、时间&#xff1a;2000-2023年 2、范围&#xff1a;31省 3、指标&#xff1a;名义GDP、国内生产总值指数、实际GDP、GDP平减…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

sshd代码修改banner

sshd服务连接之后会收到字符串&#xff1a; SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢&#xff1f; 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头&#xff0c…...

PH热榜 | 2025-06-08

1. Thiings 标语&#xff1a;一套超过1900个免费AI生成的3D图标集合 介绍&#xff1a;Thiings是一个不断扩展的免费AI生成3D图标库&#xff0c;目前已有超过1900个图标。你可以按照主题浏览&#xff0c;生成自己的图标&#xff0c;或者下载整个图标集。所有图标都可以在个人或…...