linux vmalloc 和 其友
我们展示给你的下一个内存分配函数是 vmlloc, 它在虚拟内存空间分配一块连续的内存 区. 尽管这些页在物理内存中不连续 (使用一个单独的对 alloc_page 的调用来获得每个 页), 内核看它们作为一个一个连续的地址范围. vmalloc 返回 0 ( NULL 地址 ) 如果发 生一个错误, 否则, 它返回一个指向一个大小至少为 size 的连续内存区.
我们这里描述 vmalloc 因为它是一个基本的 Linux 内存分配机制. 我们应当注意, 但是, vmalloc 的使用在大部分情况下不鼓励. 从 vmalloc 获得的内存用起来稍微低效些, 并 且, 在某些体系上, 留给 vmalloc 的地址空间的数量相对小. 使用 vmalloc 的代码如果 被提交来包含到内核中可能会受到冷遇. 如果可能, 你应当直接使用单个页而不是试图使 用 vmalloc 来掩饰事情.
让我们看看 vmalloc 如何工作的. 这个函数的原型和它相关的东西(ioremap, 严格地不 是一个分配函数, 在本节后面讨论)是下列:
#include <linux/vmalloc.h>
void *vmalloc(unsigned long size); void vfree(void * addr);
void *ioremap(unsigned long offset, unsigned long size);
void iounmap(void * addr);
NUMA (非统一内存存取) 计算机是多处理器系统, 这里内存对于特定的处理器组("节点")是"局部的". 对局部内
存的存取比存取非局部内存更快. 在这样的系统, 在当前节点分配内存是重要的. 驱动作者通常不必担心 NUMA 问题, 但是.
值得强调的是 kmalloc 和 _get_free_pages 返回的内存地址也是虚拟地址. 它们的实际 值在它用在寻址物理地址前仍然由 MMU (内存管理单元, 常常是 CPU 的一部分)管理.[31]31 vmalloc 在它如何使用硬件上没有不同, 不同是在内核如何进行分配任务上.
kmalloc 和 get_free_pages 使用的(虚拟)地址范围特有一个一对一映射到物理内存, 可能移位一个常量 PAGE_OFFSET 值; 这些函数不需要给这个地址范围修改页表. vmalloc 和 ioremap 使用的地址范围, 另一方面, 是完全地合成的, 并且每个分配建立(虚拟)内 存区域, 通过适当地设置页表.
这个区别可以通过比较分配函数返回的指针来获知. 在一些平台(例如, x86), vmalloc 返回的地址只是远离 kmalloc 使用的地址. 在其他平台上(例如, MIPS, IA-64, 以及 x86_64 ), 它们属于一个完全不同的地址范围. 对 vmalloc 可用的地址在从 VMALLOC_START 到 VAMLLOC_END 的范围中. 2 个符号都定义在 <asm/patable.h> 中.
vmalloc 分配的地址不能用于微处理器之外, 因为它们只在处理器的 MMU 之上才有意义. 当一个驱动需要一个真正的物理地址(例如一个 DMA 地址, 被外设硬件用来驱动系统的总 线), 你无法轻易使用 vmalloc. 调用 vmalloc 的正确时机是当你在为一个大的只存在于 软件中的顺序缓冲分配内存时. 重要的是注意 vamlloc 比 get_free_pages 有更多开 销, 因为它必须获取内存并且建立页表. 因此, 调用 vmalloc 来分配仅仅一页是无意义 的.
在内核中使用 vmalloc 的一个例子函数是 create_module 系统调用, 它使用 vmalloc 为在创建的模块获得空间. 模块的代码和数据之后被拷贝到分配的空间中, 使用 copy_from_user. 在这个方式中, 模块看来是加载到连续的内存. 你可以验证, 同过看
/proc/kallsyms, 模块输出的内核符号位于一个不同于内核自身输出的符号的内存范围.
使用 vmalloc 分配的内存由 vfree 释放, 采用和 kfree 释放由 kmalloc 分配的内存的 相同方式.
如同 vmalloc, ioremap 建立新页表; 不同于 vmalloc, 但是, 它实际上不分配任何内存. ioremap 的返回值是一个特殊的虚拟地址可用来存取特定的物理地址范围; 获得的虚拟地 址应当最终通过调用 iounmap 来释放.
ioremap 对于映射一个 PCI 缓冲的(物理)地址到(虚拟)内核空间是非常有用的. 例如, 它可用来存取一个 PCI 视频设备的帧缓冲; 这样的缓冲常常被映射在高端物理地址, 在 内核启动时建立的页表的地址范围之外. PCI 问题在 12 章有详细解释.
由于可移植性, 值得注意的是你不应当直接存取由 ioremap 返回的地址好像是内存指针. 你应当一直使用 readb 和 其他的在第 9 章介绍的 I/O 函数. 这个要求适用因为一些平 台, 例如 Alpha, 无法直接映射 PCI 内存区到处理器地址空间, 由于在 PCI 规格和 Alpha 处理器之间的在数据如何传送方面的不同.
实际上, 一些体系结构定义"虚拟"地址为保留给寻址物理内存. 当这个发生了,
Linux 内核利用这个特性, 并且
kernel 和 get_free_pages 地址都位于这些地址范围中的一个.
这个区别对设备驱动和其他的不直接包含到内存管理 内核子系统中的代码是透明的.
ioremap
和 vmalloc 是面向页的(它通过修改页表来工作); 结果, 重分配的或者分配的 大小被调整到最近的页边界. ioremap 模拟一个非对齐的映射通过"向下调整"被重映射的
地址以及通过返回第一个被重映射页内的偏移.
vmalloc
的一个小的缺点在于它无法在原子上下文中使用, 因为, 内部地, 它使用 kmalloc(GFP_KERNEL) 来获取页表的存储, 并且因此可能睡眠. 这不应当是一个问题
-- 如果 get_free_page 的使用对于一个中断处理不足够好, 软件设计需要一些清理.
linux vmalloc 和 其友的更多相关文章
- linux vmalloc和kmalloc
kmalloc是内核低端内存的分配,而vmalloc对应内核高端内存的分配.kmalloc()分配的内存处于3GB-high_memory之间,这一段内核空间与物理内存的映射. kmalloc保证分配 ...
- Memory Allocation API In Linux Kernel && Linux Userspace、kmalloc vmalloc Difference、Kernel Large Section Memory Allocation
目录 . 内核态(ring0)内存申请和用户态(ring3)内存申请 . 内核态(ring0)内存申请:kmalloc/kfree.vmalloc/vfree . 用户态(ring3)内存申请:mal ...
- 高端内存映射之vmalloc分配内存中不连续的页--Linux内存管理(十九)
1 内存中不连续的页的分配 根据上文的讲述, 我们知道物理上连续的映射对内核是最好的, 但并不总能成功地使用. 在分配一大块内存时, 可能竭尽全力也无法找到连续的内存块. 在用户空间中这不是问题,因为 ...
- linux内存管理之malloc、vmalloc、kmalloc的区别
kmalloc kzalloc vmalloc malloc 和get_free_page()的区别 一.简述 1. kmalloc申请的是较小的连续的物理内存,虚拟地址上也是连续的.kmalloc和 ...
- Linux设备驱动程序 之 vmalloc
vmalloc()函数的工作方式类似于kmalloc(),只不过在前者分配的内存虚拟地址是连续的,而物理地址则无须连续:这也是用户空间分配函数的工作方式:由malloc()返回的页在进程的虚拟地址空间 ...
- Linux 设备驱动 Edition 3
原文网址:http://oss.org.cn/kernel-book/ldd3/index.html Linux 设备驱动 Edition 3 By Jonathan Corbet, Alessand ...
- linux系统内核流转浅析
SJTUBEAR 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 我们通过简单 ...
- 《Linux及安全》期中总结&《Linux内核分析》期终总结
[5216 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK NINE ...
- linux 使用/proc文件系统 实现用户空间与内核模块之间通信
项目中可能会用到用户态和内核模块之间进行通信的功能.想到linux系统本身很多通信都是通过/proc文件系统来的,比如修改网络中连接跟踪表连接数限制/proc/sys/net/netfilter/nf ...
随机推荐
- cmakelists.txt中配置openg环境出现: undefined reference to symbol 'glLightfv'
cmakelists.txt中配置openg环境出现: undefined reference to symbol 'glLightfv' 解决方法: 在cmakelists.txt添加 find_p ...
- codechef Heavy-light Decompositions
Heavy-light Decompositions Problem Code: HLDOTSSubmit All submissions for this problem are available ...
- [React Native]升级React Native版本
React Native正式版本还没发布,但是小版本基本上每个月都更新1-2次.9月11号又更新了0.33版本,其中有两个增强功能正好是项目中用到的. 添加Android6.0权限验证API Add ...
- iOS 多个精致动画
iOS 多个精致动画 http://www.cocoachina.com/bbs/read.php?tid=301262 iOS 零碎小知识 http://www.cocoachina.co ...
- 中断源记录 INT0 INT1
中断源记录 INT0 INT1 用到一个单片机 使用的 P3.1 P3.3 作为唤醒口,后来发一 P3.1 和 P3.3 使用的同一个中断 INT1,这个尴尬了,只能两选 一. 查看规格书,还好 P3 ...
- 创建ROS 工作空间时出现:程序“catkin_init_workspace”尚未安装,程序“catkin_make”尚未安装。
问题:创建ROS 工作空间时出现:程序“catkin_init_workspace”尚未安装,程序“catkin_make”尚未安装. 解决方法: source /opt/ros/kinetic/se ...
- 8.5打包libgdx为一个桌面程序(jar包)
简陋的地图编辑终于做好了,于是要开始制作地图了,想导出为一个windows下可用的程序,让熟人代做地图,然后找人问了下打包流程,其实跟普通java打包为jar没什么区别,记录如下: 导出类型选第三个 ...
- 《C语言深度解剖》学习笔记之符号
第2章 符号 1.注释符号 编译器会将注释剔除,用空格代替原来的注释 y=x /* p; 编译器提示出错的原因:实际上,编译器会把“/*”当作一段注释的开始,直到出现“*/”为止. [规则 2-1]注 ...
- react+antd 点击分页为上次操作结果
最近项目中在使用antd的分页组件时发生了第一次点击分页无变化,再次点击时数据为上一次的分页结果,代码如下: setPageIndex = (pagination)=> { const page ...
- iptables 连线追踪(Connection tracking)
「连線追蹤」:提供可用於判断包相关性的额外资讯.举例来說,一次FTP session同时需要两条分离的连線,控制与资料传输各一:用於追蹤FTP连線的扩充模组,运用对於FTP恊定的认知,从控制连線上流动 ...