中移(苏州)软件技术有限公司面试问题与解答(7)—— kmalloc与vmalloc的区别与联系及使用场景

接前一篇文章:中移(苏州)软件技术有限公司面试问题与解答(0)—— 面试感悟与问题记录

本文参考以下文章:

kmalloc与vmalloc如何选择

Vmalloc与kmalloc的区别

特此致谢!

本文对于中移(苏州)软件技术有限公司面试问题中的“(6)vmalloc和kmalloc的区别?什么时候会用kmalloc、什么时候用vmalloc?”进行解答与解析。

1. kmalloc和vmalloc的区别

先来回答kmalloc和vmalloc的相同点和不同点:

  • 相同点

kmalloc和vmalloc都是Linux内核中用于内存分配的函数。

  • 不同点

1)kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续。也就是说kmalloc函数分配的内存,虚拟地址连续、物理地址也连续;而vmalloc函数分配的内存,虚拟地址连续、物理地址并不连续。通过页表来建立物理内存与虚拟内存之间的关系,从而可以将不连续的物理内存映射到连续的虚拟内存。

2)kmalloc能分配的大小有限,vmalloc能分配的大小相对较大。kmalloc函数用于在内核空间中分配小块(通常小于一个页面大小)的连续内存区域,这些内存区域可以用于存储内核数据结构和缓冲区等;vmalloc函数用于在内核空间中分配大块的虚拟内存区域,通常用于存储大型缓冲区和内存映射文件等。

3)kmalloc函数分配速度较快,vmalloc比kmalloc函数要慢。kmalloc分配的物理地址与虚拟地址只有一个__PAGE_OFFSET(即TASK_SIZE)偏移,不需要为地址段修改页表;vmalloc函数获得的物理内存是不连续的,因此它只能将这些物理内存页一个一个地进行映射。因此,在性能开销上会比直接映射大得多。

4)kmallloc使用的是slab内存分配机制,而vmalloc使用的是伙伴系统分配机制,这也是造成它们区别的根本所在

5)kmalloc可用于原子上下文,而vmalloc不可以。vmalloc函数中调用了kmalloc(GFP_KERNEL),因此也不能应用于原子上下文。

2. 什么时候用kmalloc、什么时候用vmalloc

由上边kmalloc和vmalloc的特点可知,它们适用于不同的内存分配场景。在Linux内核编程中,需要根据具体的内存分配需求选择适合的函数。

  • kmalloc的使用场景

如果需要分配小块连续内存,可以使用kmalloc函数。

  • vmalloc的使用场景

如果需要分配大块非连续虚拟内存,则需要使用vmalloc函数。vmalloc使用的正确场合是分配一大块、(虚拟地址)连续的,只在软件中存在的、用于缓冲的内存区域,不能在微处理器之外使用。

关于kmalloc和vmalloc的正确使用方法在Linux内核源码/Documentation/translations/zh_CN\core-api/memory-allocation.rst中做了详细说明,内容如下:

选择内存分配器

==============

分配内存的最直接的方法是使用kmalloc()系列的函数。而且,为了安全起见,最好使用将内存设置为零的例程,如kzalloc()。如果你需要为一个数组分配内存,有kmalloc_array()和kcalloc()辅助程序。辅助程序struct_size()、array_size()和array3_size()可以用来安全地计算对象的大小而不会溢出。

可以用 `kmalloc` 分配的块的最大尺寸是有限的。实际的限制取决于硬件和内核配置,但是对于小于页面大小的对象,使用 `kmalloc` 是一个好的做法。

用 `kmalloc` 分配的块的地址至少要对齐到ARCH_KMALLOC_MINALIGN字节。对于2的幂的大小,

对齐方式也被保证为至少是各自的大小。

用kmalloc()分配的块可以用krealloc()调整大小。与kmalloc_array()类似:以krealloc_array()

的形式提供了一个用于调整数组大小的辅助工具。

对于大量的分配,你可以使用vmalloc()和vzalloc(),或者直接向页面分配器请求页面。由vmalloc和相关函数分配的内存在物理上是不连续的。

如果你不确定分配的大小对 `kmalloc` 来说是否太大,可以使用kvmalloc()及其派生函数。它将尝试用kmalloc分配内存,如果分配失败,将用 `vmalloc` 重新尝试。对于哪些GFP标志可以与 `kvmalloc`一起使用是有限制的;请看kvmalloc_node()参考文档。注意, `kvmalloc` 可能会返回物理上不连续的内存。

如果你需要分配许多相同的对象,你可以使用slab缓存分配器。在使用缓存之前,应该用

kmem_cache_create()或kmem_cache_create_usercopy()来设置缓存。如果缓存的一部分可能被复制到用户空间,应该使用第二个函数。在缓存被创建后,kmem_cache_alloc()和它的封装可以从该缓存中分配内存。

当分配的内存不再需要时,它必须被释放。你可以使用kvfree()来处理用 `kmalloc` 、 `vmalloc`和 `kvmalloc` 分配的内存。slab缓存应该用kmem_cache_free()来释放。不要忘记用kmem_cache_destroy()来销毁缓存。

3. 函数源码

  • kmalloc函数源码

kmalloc函数在include/linux/slab.h中,代码如下:

/*** kmalloc - allocate kernel memory* @size: how many bytes of memory are required.* @flags: describe the allocation context** kmalloc is the normal method of allocating memory* for objects smaller than page size in the kernel.** The allocated object address is aligned to at least ARCH_KMALLOC_MINALIGN* bytes. For @size of power of two bytes, the alignment is also guaranteed* to be at least to the size.** The @flags argument may be one of the GFP flags defined at* include/linux/gfp_types.h and described at* :ref:`Documentation/core-api/mm-api.rst <mm-api-gfp-flags>`** The recommended usage of the @flags is described at* :ref:`Documentation/core-api/memory-allocation.rst <memory_allocation>`** Below is a brief outline of the most useful GFP flags** %GFP_KERNEL*	Allocate normal kernel ram. May sleep.** %GFP_NOWAIT*	Allocation will not sleep.** %GFP_ATOMIC*	Allocation will not sleep.  May use emergency pools.** Also it is possible to set different flags by OR'ing* in one or more of the following additional @flags:** %__GFP_ZERO*	Zero the allocated memory before returning. Also see kzalloc().** %__GFP_HIGH*	This allocation has high priority and may use emergency pools.** %__GFP_NOFAIL*	Indicate that this allocation is in no way allowed to fail*	(think twice before using).** %__GFP_NORETRY*	If memory is not immediately available,*	then give up at once.** %__GFP_NOWARN*	If allocation fails, don't issue any warnings.** %__GFP_RETRY_MAYFAIL*	Try really hard to succeed the allocation but fail*	eventually.*/
static __always_inline __alloc_size(1) void *kmalloc(size_t size, gfp_t flags)
{if (__builtin_constant_p(size) && size) {unsigned int index;if (size > KMALLOC_MAX_CACHE_SIZE)return kmalloc_large(size, flags);index = kmalloc_index(size);return kmalloc_trace(kmalloc_caches[kmalloc_type(flags, _RET_IP_)][index],flags, size);}return __kmalloc(size, flags);
}
  • vmalloc函数源码

vmalloc函数在mm/vmalloc.c中,代码如下:

/*** vmalloc - allocate virtually contiguous memory* @size:    allocation size** Allocate enough pages to cover @size from the page level* allocator and map them into contiguous kernel virtual space.** For tight control over page level allocator and protection flags* use __vmalloc() instead.** Return: pointer to the allocated memory or %NULL on error*/
void *vmalloc(unsigned long size)
{return __vmalloc_node(size, 1, GFP_KERNEL, NUMA_NO_NODE,__builtin_return_address(0));
}
EXPORT_SYMBOL(vmalloc);

至此, 中移(苏州)软件技术有限公司面试问题中的“(6)vmalloc和kmalloc的区别?什么时候会用kmalloc、什么时候用vmalloc?”就回答并解析完毕了。

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

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

相关文章

docker安装elasticsearch+kibana

目录 1.安装es 2.安装kibana 3.kibana监控es 1.安装es 拉取镜像 docker pull elasticsearch:7.6.1 创建存放配置文件、数据、插件的各个文件夹 mkdir -p /home/docker/elasticsearch/config mkdir -p /home/docker/elasticsearch/data mkdir -p /home/docker/elasticsearch…

防火墙目标NAT

目录 拓扑需求 目标NAT配置配置配置服务器映射电信&#xff08;DX&#xff09;移动&#xff08;YD&#xff09; 配置NAT策略配置目的端口转换 新建安全策略 测试 拓扑 需求 分公司设备可以通过总公司的移动链路和电信链路访问到DMZ区的http服务器 目标NAT配置 这里主要配置目标…

FFMPEG 之 DXVA2 硬解

一&#xff1a;FFMPEG 支持的硬解方式有很多&#xff1a; DXVA2、D3D11VA、CUDA、QSV、OPENCL、DRM、VAAPI、VDPAU、VIDEOTOOLBOX、MEDIACODEC。 有的支持 Windows 平台&#xff0c;有的支持 linux 平台&#xff0c;有的支持 apple ios 平台&#xff0c;…

IP路由基础

什么是路由转发 网关或者路由器根据收到的IP报文其目的地址选择一条合适的路径&#xff0c;并将报文转发到下一个路由器。在路径中的最后一跳路由器二层寻址报文转发给目的主机。 路由中包含的有哪些信息 目的网络掩码出接口下一跳 路由表发现路由的获取方式 直连路由&…

react经验10:与jquery配合使用

应用场景 老web项目进行react改造&#xff0c;为了节省时间&#xff0c;部分jquery组件仍然保留。 案例1 使用bootstrapTable组件。 node_modules准备 jquery、bootstrap、bootstrap-table 如果需要typescript&#xff0c;则额外追加 types/bootstrap、types/jquery 以上都…

《zdppy_aocrud官方教程》 08 自动生成根据ID列表删除接口

08 自动生成根据ID列表删除接口 《zdppy_aocrud官方教程》 08 自动生成根据ID列表删除接口 生成方法 服务端 import aocrud import env import orm from api import Api, respenv.load("../.env")db, BaseModel orm.get_mysql_pool_base_model_by_env()class Us…

上班族学习方法系列文章目录

上班族学习方法系列文章目录 文章目录 上班族学习方法系列文章目录前言一、时间管理二、答题实战 前言 上班族如果想提高自己&#xff0c;那么就得掌握有效的学习方法和良好的时间管理。 一、时间管理 上班族有家有业&#xff0c;考证或者提高学历备考时间不充分。需要学会精…

Mybatis 源码系列:领略设计模式在 Mybatis 其中的应用

文章目录 一、Builder模式二、工厂模式三、单例模式四、代理模式五、组合模式六、模板方式模式七、适配器模式八、装饰器模式九、迭代器模式 虽然我们都知道有23种设计模式&#xff0c;但是大多停留在概念层面&#xff0c;真实开发中很少遇到&#xff0c;Mybatis源码中使用了大…

LeetCode 第22天

235. 二叉搜索树的最近公共祖先 普通二叉树的最近公共祖先方法通用&#xff0c;但是涉及到二叉排序树的特性&#xff0c;就需要记得遍历得到的最近的一个值在p q值之间的结点&#xff0c;这个就是目标的公共祖先结点。这题算是写的比较透的了&#xff0c;用了三种方法。 class…

Flink 集成和使用 Hive Metastore

1. AWS EMR 的 Flink 使用 Hive Metastore 想在 Flink 中使用 Hive Metastore 其实只需要将 Flink Hive Connector 以及 Hive Metastore 有关的 Jar 包部署到 ${FLINK_HOME}/lib 下即可&#xff0c;稍后我们会介绍一下具体做法。但是&#xff0c;如果是 AWS EMR&#xff0c;会有…

代码随想录算法训练营DAY8 | 字符串(1)

一、LeetCode 344 反转字符串 题目链接&#xff1a; 344.反转字符串https://leetcode.cn/problems/reverse-string/ 思路&#xff1a;双指针法交换。 class Solution {public void reverseString(char[] s) {int n s.length;int left 0, right n-1;while(left < right){c…

单元/集成测试服务

服务概述 单元/集成测试旨在证明被测软件实现其单元/架构设计规范、证明被测软件不包含非预期功能。经纬恒润测试团队拥有丰富的研发经验、严格的流程管控&#xff0c;依据ISO26262/ASPICE等开展符合要求的单元测试/集成测试工作。 在ISO 26262 - part6 部分产品开发&#xff…

2024 高级前端面试题之 Node 「精选篇」

该内容主要整理关于 Node 模块的相关面试题&#xff0c;其他内容面试题请移步至 「最新最全的前端面试题集锦」 查看。 Node模块精选篇 1. package.json版本号规则2. package.json 与 package-lock.json 的关3. npm 模块安装机制4. 模块化的差异 AMD CMD COMMONJS ESMODUL5. No…

vue3:中warch监听的几种写法

作用&#xff1a;监视数据的变化&#xff08;和vue2中的watch作用一致&#xff09; 特点&#xff1a;vue3中watch只能监视以下四种数据&#xff1a; 1、ref 定义的数据 2、reactive定义的数据 3、函数返回的值&#xff08;getter函数&#xff09; 4、前面3个内容的数组 写…

AD24-第三方网表导入PCB

1、文件路径需要纯英文路径 2、生成网表 3、将网表和PCB库放进工程里 4、进行网表添加 5、新建PCB 6、选择显示差异 7、对所有东西进行更新 8、创建工程变更列表 9、执行变更 总结&#xff1a; ①导出适合AD的网表 ②创建工程 &#xff08;包含网表PCB封装库PCB&#xff09; …

最近宣布的NIST后量子密码学标准的3个关键要点

当今世界依赖于许多保护措施&#xff0c;即使您没有注意到这一点。从手机和智能技术到网站&#xff0c;从支付交易到城市基础设施&#xff0c;人们经常与之互动的一切&#xff0c;都通过保护和检查技术来保护。量子计算机能够快速轻松地打破这些保护措施&#xff0c;这是政府和…

go语言-字符串处理常用函数

本文介绍go语言处理字符串类型的常见函数。 ## 多行字符串 在 Go 中创建多行字符串非常容易。只需要在你声明或赋值时使用 () 。 str : This is a multiline string. ## 字符串的拼接 go // fmt.Sprintf方式拼接字符串 str1 : "abc" str2 : "def" …

【Qt学习笔记】(一)初识Qt

Qt学习笔记 1 使用Qt Creator 新建项目2 项目代码解释3 创建第一个 Hello World 程序4 关于内存泄漏问题5 Qt 中的对象树6 关于 qDebug&#xff08;&#xff09;的使用7 使用其他方式创建一个 Hello World 程序&#xff08;编辑框和按钮方式&#xff09;8 关于 Qt 中的命名规范…

【Python_PySide6学习笔记(三十二)】无边框窗体实现点击任务栏图标最小化,再次点击恢复窗体显示

无边框窗体实现点击任务栏图标最小化,再次点击恢复窗体显示 无边框窗体实现点击任务栏图标最小化,再次点击恢复窗体显示前言一、无边框窗体设置二、点击任务栏图标显示和隐藏设置三、实现效果无边框窗体实现点击任务栏图标最小化,再次点击恢复窗体显示 前言 本文介绍基于 …

docker 无法执行systemctl

docker 无法执行systemctl:System has not been booted with systemd as init system (PID 1). Cant operate. Failed to connect to bus: Host is down 背景 System has not been booted with systemd as init system (PID 1). Cant operate. Failed to connect to bus: Hos…