浅析linux内核内存管理之kmalloc
作者:李万鹏
在SLAB的高速缓存中有普通高速缓存和专用高速缓存,平时用kmem_cache_create创建的是专用高速缓存,比如存放task_struct,mm_struct的高速缓存。普通高速缓存主要供kmalloc使用。第一个高速缓存叫kmem_cache,存放在cache_cache变量中,这个cache专门用于为其他cache分配描述符。
内存区大小的范围一般包括13个几何分布的内存区。一个叫做malloc_sizes的表(其元素类型为cache_sizes)分别指向26个高速缓存描述符,与其相关的内存区大小为32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072。
下面是kmalloc()的实现,kernel 2.6.11:
注意这里与malloc_sizes都包含了kmalloc_sizes.h头文件,在下边列出:可以看到CACHE是一个宏,在malloc_sizes与kmalloc中的含义是不一样的,在malloc_sizes中:
表示malloc_sizes的成员是13个大小不同的内存区,而kmalloc中:
就是让32~131072依次与size进行大小比较,开始的时候i=0,如果找到的cache的object size比请求的size大,那么就调用kmem_cache_alloc从相应的cache分配object,这里i++为了对应相应的malloc_sizes[i]。
kmalloc()主要调用__kmalloc()进行分配:在__kmalloc中找一个大小比请求的大小大的cache。然后从那个cache中进行分配,对于每种大小,都有两个高速缓存:一个适用于ISA DMA,另一个适用于常规分配。这里调用__cache_alloc()在适当的cache中分配object。
调用kfree释放分配到的内存:这里调用看了__cache_free释放object到cache。
kmalloc的第一个参数是要分配的块的大小,第二个参数是分配标志(flags)。
最常用的标志是GFP_KERNEL,它表示内存分配的(最终总是调用get_free_pages来实现实际的分配,这就是GFP_前缀的由来)是代表运行在内核空间的进程执行的。换句话说,这意味着调用它的函数正代表某个进程执行系统调用。使用GFP_KERNEL允许kmalloc在空闲内存较少时把当前进程转入休眠以等待一个页面。因此,使用GFP_KERNEL分配内存的函数必须是可重入的。在当前进程休眠时,内核会采取适当的行动,或者是把缓冲区的内存刷写到硬盘上,或者是从一个用户进程换出内存,以获取一个内存页面。
GFP分配标志并不是始终适用,有时kmalloc是在进程上下文之外被调用的,例如在中断处理例程,tasklet以及内核定时器中调用。这种情况下current进程就不应该休眠,驱动程序则应该换用GFP_ATOMIC标志。内核通常会为原子性的分配预留一些空闲页面。使用GFP_ATOMIC标志时,kmalloc甚至可以调用最后一个空闲页面。不过如果连最后一页都没有了,分配就返回失败。
下边来看一些常用的符号,这些符号都包含在<linux/gfp.h>:
GFP_ATOMIC
用于在中断处理例程或其他运行于进程上下文之外的代码中分配内存,不会休眠。
GFP_KERNEL
内核内存的通常分配方法,可能引起休眠。
GFP_USER
用于为用户空间分配内存,可能会引起休眠。
GFP_NOIO
GFP_NOFS
这两个标志的功能类似于GFP_KERNEL,但是为内核分配内存的工作方式添加了一些限制。具有GFP_NOFS标志的分配不允许执行任何文件系统调用,而GFP_NOIO禁止任何I/O的初始化。
__GFP_DMA
该标志请求分配发生在可进行DMA的内存区段中。
__GFP_HIGHMEM
这个标志表明分配的内存科位于高端内存。
__GFP_COLD
表示从冷高速缓存分配,即per cpu pages的cold page。
下面一个测试程序,模拟mmu查表过程:
测试结果:
KMALLOC PK VMALLOC
- kmalloc是基于slab的,所以速度比较快。vmalloc的内部会调用到kmalloc,但是只是分配vm_struct描述符,和分配nr_pages指针数组,这个数组里的每个元素指向vm_struct对应的非连续内存区域的每一个页描述符结构。真正的分页是通过alloc_page一页一页的从buddy system分配。所以物理地址是不连续的,一页一页分配物理地址不一定啥地方了。kmalloc分配的页已经映射好了,而vmalloc分配后一级一级建立页表很是麻烦。
- 高端内存使用的是小页,所以使用vmalloc的时候不会打印出"Use Large Page PSE = 1"。
- 在中断上下文中可以使用kmalloc,前提是使用GFP_ATOMIC标志,而中断上下文中不能用vmalloc替代kmalloc,vmalloc调用kmalloc和alloc_page都使用了GFP_KERNEL标志,这个标志可能因此进程休眠。
- 用vmalloc分配页修改的是内核页表部分,并没有修改进程的相关项,在访问的时候需要通过page fault来同步,而kmalloc就不需要这一过程。
分享到:
相关推荐
Linux常见驱动源码分析(kernel hacker修炼之道)--李万鹏 李万鹏 IBM Linux Technology Center kernel team 驱动资料清单内容如下: Linux设备模型(中)之上层容器.pdf Linux设备模型(上)之底层模型.pdf Linux...
常见驱动源码分析( LINUX kernel hacker修炼之道)-李万鹏
常见驱动源码分析(kernel hacker修炼之道)
如果刚刚对linux的kernel有兴趣,想了解点什么的话,请先看看此书吧,她风趣幽默的介绍了linux的发展趣事,让你开心快乐之余慢慢领会linux的魅力,让你了解学习掌握kernel的方法。其中的很多建议经过我的实践和摸索...
国嵌的笔记 非常的不容易 里面驱动 包括USB LCD 文件系统 内存管理有非常详细 的记录
Linux PCI驱动牛人写的论文,有一定参考价值
有关hacker 的文章和资料分享给大家
渗透测试教程资料
Algorithm-HackerRank-Solutions-In-Scala.zip,在scala中解决hackerrank的挑战,算法是为计算机程序高效、彻底地完成任务而创建的一组详细的准则。
黑客入门教材,理论结合实践,通俗易懂。为读此书,先学英文也值得。
HackerRank-Interview-Preparation-Kit-master.rar
rails-hackernews-reddit-producthunt-clone, 黑客 news/reddit/social 链接分享网站 用 Rails 构建 Rails 上的 Reddit-Hackernews-ProductHunt克隆演示 这是一个 readme.md的Ruby on Rails 应用程序,模仿了 Hacker...
hacker-history.pdf hacker-history.pdf
Hacker 2012 - Final Transfer Readme =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Thank you for downloading Hacker 2012! Registration ------------------------------------ If you like the game, ...
Process Hacker是一款功能丰富的系统程序,比windows自带的任务管理器功能更强大。用户只要借助该程序就可以方便,快捷地查看相关进程的速度,内存,及模块等等,除此,还可以对相关的进程进行管理工作。
Process Hacker是一款针对高级用户的安全分析工具,它可以帮助研究人员检测和解决软件或进程在特定操作系统环境下遇到的问题。除此之外,它还可以检测恶意进程,并告知我们这些恶意进程想要实现的功能。 Process ...
Resource Hacker 可以被用来: 1. 查看 Win32 可执行和相关文件的资源 (*.exe, *.dll, *.cpl, *.ocx),在已编译和反编译的格式下都可以。 2. 提取 (保存) 资源到文件 (*.res) 格式,作为二进制,或作为反编过的译...
Process Hacker是一款强大的系统进程管理工具,开源,并且还可以显示CPU、GPU、IO、内存等相关使用信息。 官网地址:https://processhacker.sourceforge.io/ git地址:...
Process Hacker是一款强大的系统进程管理工具,开源,并且还可以显示CPU、GPU、IO、内存等相关使用信息。 官网地址:https://processhacker.sourceforge.io/ git地址:...
前端开源库-esdoc-hacker-visionESDoc Hacker Vision,用于ESDoc的Hacker Vision前端插件