A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 梦缠绕的时候 黑马粉丝团   /  2018-9-12 09:35  /  998 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

在用户空间动态申请内存

在用户空间中动态申请内存的函数为 malloc(),这个函数在各种操作上的使用都是一致的。与之对应的释放函数为 free()。

对于 Linux 而言,C 库的 malloc() 函数一般通过 brk() 和 mmap() 两个系统调用从内核申请内存。


在内核空间动态申请内存

在 Linux 内核空间中申请内存涉及的函数主要包括 kmalloc()、__get_free_pages() 和 vmalloc() 等。这里只介绍这3种。

1. kmalloc()

函数原型为:

void * kmalloc(size_t size, int flags);

size:要分配的块的大小

flags:分配标志,用于控制 kmalloc() 的行为,最常用是 GFP_KERNEL 和 GFP_ATOMIC

分配标志为 GFP_KERNEL 时,表示在内核空间的进程中申请内存。

使用 GFP_KERNEL 标志申请内存时,若暂时不能满足,则进程会睡眠等待也,即会引起阻塞,因此不能中断上下文或持有自旋锁的时候使用 GFP_KERNEL 申请内存。

由于在中断处理函数、tasklet 和内核定时器等非进程上下文中不能阻塞,所以此时驱动应当使用 GFP_ATOMIC 标志来申请内存。当使用 GFP_ATOMIC 标志申请内存时,若不存在空页,则不等待,直接返回。

2. __get_free_pages()

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

__get_free_pages() 系列函数/宏包括 get_zeroed_page()、__get_free_page() 和 __get_free_pages()。

kmalloc() 的底层依赖于 __get_free_pages() 来实现的。

3. vmalloc()

vmalloc() 一般只为存在于软件中(没有对应的硬件意义)的较大的顺序缓冲区分配内存,vmalloc() 远大于 __get_free_pages() 的开销,为了完成 vmalloc(),新的页表项需要被建立,因此,只是调用 vmalloc() 来分配少量的内存时不妥的。

vmalloc() 申请的内存使用 vfree() 释放。

vmalloc() 不能用在原子上下文中,因为它的内部实现了标志位 GFP_KERNEL 的 kmalloc()。

vmalloc() 在申请内存时,会进行内存的映射,改变页表项,不像 kmalloc() 实际用的是开机过程中就映射好的 DMA 和常规区域的页表项。因此 vmalloc() 的虚拟地址和物理地址不是一个简单的线性映射。

4. 总结

kmalloc() 和 __get_free_pages() 申请的内存在物理上连续,而 vmalloc() 申请的内存在物理上不连续


1 个回复

倒序浏览

很不错,受教了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马