Linux 内存分配

Linux内存管理:伙伴系统与页块分配

一、伙伴系统buddy

Linux系统是以块来分配物理内存的,0,1,2,3.....MAX_ORDER-1。MAX_ORDER=11,总共有11个链表,存放的是n阶的页块。

分配和释放都是以页块为单位进行的。

伙伴系统:

1、两个n阶页块互为伙伴。

2、页块的第一个物理页面的阶数必须是n的整数倍。

3、

alloc_page

alloc_zero_page

alloc_dma_page

__get_free_page

__get_free_pages

----------->alloc_pages--->alloc_pages_node_mask-->alloc_page_from_freelist

alloc_page_slowpath

二、slab分配

三、kmalloc

四、vmalloc

五、kmap

六、快速路径和慢速路径

<think>我们正在讨论Linux内存分配中的标志位及其含义。根据用户的问题,我们需要解释内存分配时使用的标志位(如GFP_KERNEL, GFP_ATOMIC等)及其作用。首先,我们需要明确:这些标志位用于内核内存分配函数(如kmalloc,vmalloc等)中,以控制内存分配的行为。它们定义在<linux/gfp.h>头文件中。常见的标志位可以分为几个类别:行为修饰符、区域修饰符、类型标志。我们将重点介绍一些最常用的标志。1.**行为修饰符**:控制分配器如何分配内存。- `__GFP_WAIT`:允许分配过程中休眠(现在已整合到类型标志中,如GFP_KERNEL隐含此标志)。-`__GFP_HIGH`:分配请求是高优先级的,即使内存紧张也要尽量满足。-`__GFP_IO`:允许分配过程中进行I/O操作(如换页)。-`__GFP_FS`:允许调用文件系统相关操作。- `__GFP_COLD`:请求冷页(长时间未使用的页,适合DMA操作)。 2. **区域修饰符**:指定从哪个内存区域分配(如DMA区域、普通区域等)。-`__GFP_DMA`:从DMA区域分配(适用于需要DMA操作的内存)。- `__GFP_HIGHMEM`:从高端内存区域分配。3.**类型标志**:组合了行为修饰符和区域修饰符,是常用的预定义组合。- `GFP_KERNEL`:内核中最常用的标志,允许休眠、I/O操作和文件系统操作。适用于可以睡眠的进程上下文。-`GFP_ATOMIC`:用于原子上下文(如中断处理程序、软中断等),不允许休眠,因此分配失败的可能性较高。- `GFP_HIGHUSER`:用于用户空间的高端内存分配。-`GFP_NOIO`:不允许I/O操作,但可以休眠。用于避免I/O死锁的情况(如文件系统操作中需要分配内存,但又不允许进行I/O操作)。-`GFP_NOFS`:不允许文件系统操作,但可以休眠。用于避免文件系统死锁。另外,还有一些标志用于特殊情况:- `__GFP_ZERO`:分配内存后将其初始化为0。-`__GFP_NOWARN`:当分配失败时,不打印警告信息。 需要注意的是,这些标志位可能会随着内核版本而变化,因此具体细节应参考相应版本的内核源码。下面我们通过一个例子来说明如何使用这些标志位:```c#include<linux/slab.h>//包含kmalloc等函数的声明void*ptr;//在可以睡眠的上下文中,使用GFP_KERNEL分配内存ptr =kmalloc(size, GFP_KERNEL);if (!ptr){//处理分配失败} //在原子上下文中,使用GFP_ATOMICptr =kmalloc(size,GFP_ATOMIC);if (!ptr){//处理分配失败} ```在最新的内核版本中,标志位的定义和使用可能会有调整。例如,从Linux2.6.22开始,引入了GFP标志的重新组织,将一些标志位进行了合并和调整。因此,建议查阅当前内核版本的头文件。 引用[1]提到了进程标志位(PF_*),这与内存分配标志位不同。内存分配标志位是GFP_*(GetFree Page的缩写),而PF_*是进程描述符中的状态标志。因此,我们这里讨论的是GFP_*标志。引用[2]提到了Unix系统将内存分为内核部分和用户部分,这为我们理解内存分配提供了背景:内核内存分配是从内核空间的内存池中分配,而用户空间的内存分配则是通过系统调用(如brk,mmap)从用户空间的内存池中分配。总结一下,Linux内存分配标志位用于控制内存分配的行为和区域,根据不同的上下文选择合适的标志位非常重要,特别是在内核开发中。§§相关问题§§1.在Linux内核中,什么时候使用GFP_ATOMIC标志? 2. GFP_KERNEL和GFP_ATOMIC的主要区别是什么?3.如何在内核代码中分配内存并将其初始化为零?4.什么是高端内存(HighMemory)?在分配高端内存时应该使用什么标志? 5.为什么在中断处理程序中不能使用GFP_KERNEL标志?</think>### Linux内存分配标志位及其作用 在Linux内核中,内存分配标志位(GFP flags)控制内存分配器的行为,定义在`<linux/gfp.h>`头文件中。这些标志位通过位掩码组合使用,主要分为三类: #### 1. **区域修饰符(Zone Modifiers)** 指定内存分配的物理区域: - `__GFP_DMA`:从DMA可用区域分配(通常 <16MB) - `__GFP_HIGHMEM`:从高端内存区域分配(32位系统 >896MB) - `__GFP_MOVABLE`:分配可移动页(用于内存热插拔) #### 2. **行为修饰符(Behavior Modifiers)** 控制分配策略: - `__GFP_WAIT`:允许分配过程休眠(已整合到类型标志中) - `__GFP_HIGH`:高优先级分配,可访问紧急内存池 - `__GFP_IO`:允许启动I/O操作(如页面回收) - `__GFP_FS`:允许调用文件系统操作 - `__GFP_COLD`:请求较少使用的"冷"页 - `__GFP_ZERO`:分配后自动清零内存 - `__GFP_NOWARN`:分配失败时不产生警告 #### 3. **类型标志(Type Flags)** 常用组合(包含隐式行为): - `GFP_KERNEL`:标准内核分配 $$ \text{(__GFP_WAIT | __GFP_IO | __GFP_FS)} $$ 允许休眠和I/O操作,适用于进程上下文[^1]。 - `GFP_ATOMIC`:原子上下文分配 $$ \text{(__GFP_HIGH)} $$ 禁止休眠,用于中断/原子上下文[^2]。 - `GFP_USER`:用户空间分配,可能被阻塞 - `GFP_HIGHUSER`:用户空间高端内存分配 - `GFP_NOIO`/`GFP_NOFS`:禁止I/O/文件系统操作(用于避免死锁) #### 典型应用场景 ```c // 进程上下文分配(可休眠) void *buf = kmalloc(size, GFP_KERNEL); // 中断处理程序分配(不可休眠) void *irq_buf = kmalloc(size, GFP_ATOMIC); // 分配DMA内存 void *dma_buf = kmalloc(size, GFP_DMA | GFP_KERNEL); ``` > **关键机制**:当`GFP_KERNEL`分配失败时,内核会尝试内存回收(包括文件系统操作和I/O),而`GFP_ATOMIC`失败则直接返回NULL[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值