kmalloc/kfree,vmalloc/vfree函数用法和区别

1.kmalloc

1>kmalloc内存分配和malloc相似,除非被阻塞否则他执行的速度非常快,而且不对获得空间清零.

tiger说明:在用kmalloc申请函数后,要对起清零

memset()函数对申请的内存进行清零。

2>kamlloc函数原型:

#include<Linux/slab.h>

Void *kmalloc(size_t size, int flags);

(1)第一个参数是要分配的块的大小

(2)第二个参数是分配标志(flags),他提供了多种kmalloc的行为。

(3)第三个最常用的GFP_KERNEL

A.表示内存分配(最终总是调用get_free_pages来实现实际的分配;这就是GFP前缀的由来)是代表运行在内核空间的进程执行的。使用GFP_KERNEL容许kmalloc在分配空闲内存时候如果内存不足容许把当前进程睡眠以等待。因此这时分配函数必须是可重入的。如果在进程上下文之外如:中断处理程序、tasklet以及内核定时器中这种情况下current进程不该睡眠,驱动程序该使用GFP_ATOMIC.

B.GFP_ATOMIC

用来从中断处理和进程上下文之外的其他代码中分配内存. 从不睡眠.

C.GFP_KERNEL

内核内存的正常分配. 可能睡眠.

D.GFP_USER

用来为用户空间页来分配内存; 它可能睡眠.

E.GFP_HIGHUSER

如同 GFP_USER, 但是从高端内存分配, 如果有. 高端内存在下一个子节描述.

F.GFP_NOFS,GFP_NOIO

这个标志功能如同 GFP_KERNEL, 但是它们增加限制到内核能做的来满足请求. 一个 GFP_NOFS 分配不允许进行任何文件系统调用, 而 GFP_NOIO 根本不允许任何 I/O 初始化. 它们主要地用在文件系统和虚拟内存代码, 那里允许一个分配睡眠, 但是递归的文件系统调用会是一个坏注意.

上面列出的这些分配标志可以是下列标志的相或来作为参数, 这些标志改变这些分配如何进行:

__GFP_DMA

这个标志要求分配在能够 DMA 的内存区. 确切的含义是平台依赖的并且在下面章节来解释.

__GFP_HIGHMEM

这个标志指示分配的内存可以位于高端内存.

__GFP_COLD

正常地, 内存分配器尽力返回"缓冲热"的页 -- 可能在处理器缓冲中找到的页. 相反, 这个标志请求一个"冷"页, 它在一段时间没被使用. 它对分配页作 DMA 读是有用的, 此时在处理器缓冲中出现是无用的. 一个完整的对如何分配 DMA 缓存的讨论看"直接内存存取"一节在第 1 章.

__GFP_NOWARN

这个很少用到的标志阻止内核来发出警告(使用 printk ), 当一个分配无法满足.

__GFP_HIGH

这个标志标识了一个高优先级请求, 它被允许来消耗甚至被内核保留给紧急状况的最后的内存页.

Ø  __GFP_REPEAT

__GFP_NOFAIL

__GFP_NORETRY

这些标志修改分配器如何动作, 当它有困难满足一个分配. __GFP_REPEAT 意思是" 更尽力些尝试" 通过重复尝试 -- 但是分配可能仍然失败. __GFP_NOFAIL 标志告诉分配器不要失败; 它尽最大努力来满足要求. 使用 __GFP_NOFAIL 是强烈不推荐的; 可能从不会有有效的理由在一个设备驱动中使用它. 最后, __GFP_NORETRY 告知分配器立即放弃如果得不到请求的内存.

Ø  内存区段

__GFP_DMA和__GFP_HIGHMEM的使用与平台相关,linux把内存分成3个区段:可用于DMA的内存、常规内存、以及高端内存。X86平台上ISA设备DMA区段是内存的前16MB,而PCI设备无此限制。

内存区后面的机制在 mm/page_alloc.c 中实现, 而内存区的初始化在平台特定的文件中, 常常在 arch 目录树的 mm/init.c。

3>kamlloc的使用方法:

Linux 处理内存分配通过创建一套固定大小的内存对象池. 分配请求被这样来处理, 进入一个持有足够大的对象的池子并且将整个内存块递交给请求者. 驱动开发者应当记住的一件事情是, 内核只能分配某些预定义的, 固定大小的字节数组.

如果你请求一个任意数量内存, 你可能得到稍微多于你请求的, 至多是 2 倍数量. 同样, 程序员应当记住 kmalloc 能够处理的最小分配是 32或者 64字节, 依赖系统的体系所使用的页大小. kmalloc 能够分配的内存块的大小有一个上限. 这个限制随着体系和内核配置选项而变化. 如果你的代码是要完全可移植,它不能指望可以分配任何大于 128 KB.如果你需要多于几个 KB,但是,有个比 kmalloc更好的方法来获得内存。在设备驱动程序或者内核模块中动态开辟内存,不是用malloc,而是kmalloc ,vmalloc,或者用get_free_pages直接申请页释放内存用的是kfree,vfree,或free_pages. kmalloc函数返回的是虚拟地址(线性地址). kmalloc特殊之处在于它分配的内存是物理上连续的,这对于要进行DMA的设备十分重要. 而用vmalloc分配的内存只是线性地址连续,物理地址不一定连续,不能直接用于DMA.

  注意kmalloc最大只能开辟128k-1616个字节是被页描述符结构占用了。kmalloc用法参见khg.

  内存映射的I/O口,寄存器或者是硬件设备的RAM(如显存)一般占用F0000000以上的地址空间。在驱动程序中不能直接访问,要通过kernel函数vremap获得重新映射以后的地址。

  另外,很多硬件需要一块比较大的连续内存用作DMA传送。这块内存需要一直驻留在内存,不能被交换到文件中去。但是kmalloc最多只能开辟大小为32XPAGE_SIZE的内存,一般的PAGE_SIZE=4kB,也就是128kB的大小的内存。

3.kmalloc和vmalloc的区别

• vmalloc()与 kmalloc()都可用于分配内存

• kmalloc()分配的内存处于3GB~high_memory之 间,这段内核空间与物理内存的映射一一对应

•vmalloc()分配的内存在 VMALLOC_START~4GB之间,这段非连续内 存区映射到物理内存也可能是非连续的

• 在内核空间中调用kmalloc()分配连续物理空间,而调用vmalloc()分配非物理连续空间。

• 把kmalloc()所分配内核空间中的地址称为内核逻辑地址

• 把vmalloc()分配的内核空间中的地址称 为内核虚拟地址

• vmalloc()在分配过程中须更新内核页表

总结:

1.kmalloc和vmalloc分配的是内核的内存,malloc分配的是用户的内存

2.kmalloc保证分配的内存在物理上是连续的, kmalloc()分配的内存在0xBFFFFFFF-0xFFFFFFFF以上的内存中,driver一般是用它来完成对DS的分配,更适合于类似设备驱动的程序来使用;

3.vmalloc保证的是在虚拟地址空间上的连续,vmalloc()则是位于物理地址非连续,虚地址连续区,起始位置由VMALLOL_START来决定,一般作为交换区、模块的分配。

3.kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相对较大(因为vmalloc还可以处理交换空间)。

4.内存只有在要被DMA访问的时候才需要物理上连续,vmalloc比kmalloc要慢

5.vmalloc使用的正确场合是分配一大块,连续的,只在软件中存在的,用于缓冲的内存区域。不能在微处理器之外使用。

6.vmalloc 中调用了 kmalloc (GFP—KERNEL),因此也不能应用于原子上下文。

7.kmalloc和 kfree管理内核段内分配的内存,这是真实地址已知的实际物理内存块。

8.vmalloc对应于vfree,分配连续的虚拟内存,但是物理上不一定连续。

9.kmalloc分配内存是基于slab,因此slab的一些特性包括着色,对齐等都具备,性能较好。物理地址和逻辑地址都是连续的

10.kmalloc分配的内存比较小,32-64kb,128kb这样子,如果需要申请大内存,又不需要和硬件打交道如DMA,用vmalloc就可以。

11.kmalloc申请的内存物理和虚拟地址上都是连续的,申请范围在3GB-high_memory,vmallo物理不连续,虚拟地址连续,申请范围在VMALLOC_START-4GB所以vmalloc申请的内存尽量不和硬件打交道了。

12.性能上kamlloc比较优,因为vmalloc物理上不连续,需要建立大量的页表管理。


在设备驱动程序或者内核模块中动态开辟内存,不是用malloc,而是kmalloc ,vmalloc,或者用get_free_pages直接申请页。释放内存用的是kfree,vfree,或free_pages. kmalloc函数返回的是虚拟地址(线性地址). kmalloc特殊之处在于它分配的内存是物理上连续的,这对于要进行DMA的设备十分重要. 而用vmalloc分配的内存只是线性地址连续,物理地址不一定连续,不能直接用于DMA.

  注意kmalloc最大只能开辟128k-16,16个字节是被页描述符结构占用了。kmalloc用法参见khg.

  内存映射的I/O口,寄存器或者是硬件设备的RAM(如显存)一般占用F0000000以上的地址空间。在驱动程序中不能直接访问,要通过kernel函数vremap获得重新映射以后的地址。

  另外,很多硬件需要一块比较大的连续内存用作DMA传送。这块内存需要一直驻留在内存,不能被交换到文件中去。但是kmalloc最多只能开辟大小为32XPAGE_SIZE的内存,一般的PAGE_SIZE=4kB,也就是128kB的大小的内存。


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

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

相关文章

SQL Server开发接口生成方法

为提高开发效率&#xff0c;生成固定格式的接口是必须的&#xff0c;以下以提供新增/修改/删除/读取接口为例&#xff1a; 以常见的表结构为例&#xff0c;特殊表结构可自己尝试去调整方法 主要通过系视图 sys.columns生成方法:为包含列的对象&#xff08;如视图或表&#xff0…

vue-cli2定制ant-design-vue主题

本篇是vue-cli2定制主题&#xff0c;vue-cli3通过vue.config.js定制主题点击此处 1.引入less和less-loader&#xff08;如果报错&#xff0c;请将less-loader版本更改到5.0.0&#xff09; npm install less less-loader --save2.在 vue cli 2 中定制主题&#xff0c;修改build…

python中thread的setDaemon、join的用法

From: http://doudouclever.blog.163.com/blog/static/17511231020127232303469/ python中得thread的一些机制和C/C不同&#xff1a;在C/C中&#xff0c;主线程结束后&#xff0c;其子线程会默认被主线程kill掉。而在python中&#xff0c;主线程结束后&#xff0c;会默认等待子…

谈谈软件兼容性测试

1.软件兼容性测试兼容性测试之待测试项目在特定的硬件平台上&#xff0c;不同的应用软件不同&#xff0c;不同的操作系统平台上&#xff0c;在不同的网络等环境中能正常的运行的测试。兼容性测试的目的&#xff1a;带测试项目在不同的操作系统上正常运行&#xff0c;包括待测试…

YUV视频格式分析

Andrew Huang <bluedrum163.com> 转载请注明作者及联络方式在摄像头之类编程经常是会碰到YUV格式,而非大家比较熟悉的RGB格式. 我们可以把YUV看成是一个RGB的变种来理解.YUV的原理是把亮度与色度分离&#xff0c;研究证明,人眼对亮度的敏感超过色度。利用这个原理&#x…

自定义ant中table表格的展开图标 修改ant-vue-design中嵌套表格table的expandIcon自定义图标

效果&#xff1a; 1. <a-table:expandIcon"expandIcon":loading"loading":columns"columns":data-source"data"class"components-table-demo-nested"change"onChangeTable":scroll"{x:1300,y:y}":p…

Foundationd和Application Kit的类层次

Foundationd类 Application Kit类 转载于:https://www.cnblogs.com/ikodota/archive/2012/08/01/2618590.html

python多线程编程(1): python对多线程的支持

From: http://www.cnblogs.com/holbrook/archive/2012/03/01/2376408.html 前面介绍过多线程的基本概念&#xff0c;理解了这些基本概念&#xff0c;掌握python多线程编程就比较容易了。 在开始之前&#xff0c;首先要了解一下python对多线程的支持。 虚拟机层面 Python虚拟机…

三个数从小到大排序

描述 现在要写一个程序&#xff0c;实现给三个数排序的功能 输入输入三个正整数 输出给输入的三个正整数排序 样例输入20 7 33 样例输出 7 20 33 测试代码 1 #include "stdio.h"2 3 int main()4 {5 int a, b, c, t;6 scanf("%d%d%d", &a, &…

监听vuex的某条数据

需要现在计算属性里获取 computed: {tabType: {get() {return this.$store.state.tabType;},set(val) {this.$store.state.tabType val;},}},watch: {tabType(val) {this.allType this.$store.state.tabType;}, }

dup和dup2的使用方法

/*本文通过标准输出的重定向和恢复的过程来解释dup和dup2的使用方法*/#include <stdio.h> #include <unistd.h>#include <fcntl.h>//STDIN_FILENO标准输入描述符&#xff08;0&#xff09;//STDOUT_FILENO标准输出描述符&#xff08;1&#xff09; //STDERR_…

django时间问题和时区设置

django里默认设置了一个时区&#xff0c;我在django里调time获取时间&#xff0c;与系统时间出现不一致的情况&#xff0c;所以我们需要重启设置时区&#xff0c;如下&#xff1a;在settings.py里面把TIME_ZONE设为&#xff1a;Etc/GMT-8 转载于:https://blog.51cto.com/linuxs…

python多线程编程(2): 线程的创建、启动、挂起和退出

From: http://www.cnblogs.com/holbrook/archive/2012/03/02/2376940.html 如上一节&#xff0c;python的threading.Thread类有一个run方法&#xff0c;用于定义线程的功能函数&#xff0c;可以在自己的线程类中覆盖该方法。而创建自己的线程实例后&#xff0c;通过Thread类的…

记录ie下报XMLHttpRequest: 网络错误 0x80070005, 拒绝访问。

问题&#xff1a; 同样的调用接口&#xff0c;在谷歌是没有问题的&#xff0c;但是在ie下报错XMLHttpRequest: 网络错误 0x80070005, 拒绝访问。 1.分析&#xff1a; 对比了一下&#xff0c;相同的是接口传递参数错误导致报错&#xff0c;传递的参数自动带上了 " "…

getopt和getopt_long函数

平时在写程序时常常需要对命令行参数进行处理&#xff0c;当命令行参数个数较多时&#xff0c;如果按照顺序一个一个定义参数含义很容易造成混乱&#xff0c;而且如果程序只按顺序处理参数的话&#xff0c;一些“可选参数”的功能将很难实现。 在Linux中&#xff0c;我们可以使…

MVC3.0+DWZ探索

将themes 文件移到 js文件 index.html 转载于:https://www.cnblogs.com/acyy/archive/2012/08/03/2621594.html

棋盘覆盖

在一个2k x 2k ( 即&#xff1a;2^k x 2^k )个方格组成的棋盘中&#xff0c;恰有一个方格与其他方格不同&#xff0c;称该方格为一特殊方格&#xff0c;且称该棋盘为一特殊棋盘。在棋盘覆盖问题中&#xff0c;要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外…

VMM2012应用指南之12- 创建自助服务用户并分配云

河北经贸大学 王春海如果要在云中创建、管理虚拟机&#xff0c;首先要创建自助服务帐户&#xff0c;在创建用户角色的同时即可以分配云。本节介绍这部分内容。【说明】在做下面的这个操作的时候&#xff0c;需要向“库”服务器再添加另外一个库的路径&#xff0c;用于保存云中的…

分隔符字符串处理(strtok与strsep区别)

1、strtok原型与应用原型&#xff1a;char *strtok(char *src, const char *delim);功能&#xff1a;将src(原字符串)根据delim(分隔符串)分解为不同子串&#xff08;连续算一个&#xff09;返回&#xff1a;属于当前分割的子串&#xff0c;当前没有分割的子串时返回NULL#inclu…