[linux内存]伙伴系统学习笔记(三)--分配器API

1,分配器API

http://blog.csdn.net/kickxxx/article/details/9287003

伙伴系统只能分配2的整数幂个页。因此申请时,需要指定请求分配的阶。

2,分配页,

所有分配伙伴系统的函数分配页最终都会调用到alloc_pages_nodemask()函数

static inline struct page*alloc_pages_nodemask(int nid,gfp_t gfp_mask,unsigned int order)
nid:指的是从哪一个节点分配
gfp_mask:一些标志
order:分配阶

该函数主要分为两大步:

1,选择页,在某一个节点的某一个可迁移区域找到足够的连续的页,流程是从指定的管理区开始扫描管理区-->找到充足的管理区从认定的管理区开始遍历,直到找到一个拥有足够空间的管理区例如,如果high_zoneidx对应的ZONE_HIGHMEM,则遍历顺序为HIGHMEM-->NORMAL-->DMA如果high_zoneidx对应ZONE_NORMAL,则遍历顺序为NORMAL-->DMA-->从指定的迁移类型链表中分配内存-->如果在指定迁移类型中找不到则到其他的迁移类型中去寻找(get_page_from_freelist()) ,如果第二步在各个区域都找不到可以满足分配的内存了,那么说明管理区的内存已经确实不够了,于是开始启用一条慢速的途径来分配( __alloc_pages_slowpath),包括尝试去换出一些不经常使用的页等等,内核会在这次分配中表现得更为积极,其中的细节涉及到了其他一些复杂的东西

2,在第一部中只是确定有那么多的空闲的页,还不确定其是否是连续的,如果是连续的则移除页,将要分配的页从当前的伙伴系统移除~可能要按照伙伴系统的方式分解并重排内存分区。如果只是分配一页,内核会进行优化,分配一页的情况不会从伙伴系统分配,而是取自per-CPU缓存,如果当前per-CPU缓存为空,那么需要调用rmqueue_bulk()函数从伙伴系统分配适当的页填充到per-CPU缓存里,如果是要分配多于一页的内存,那么会调用__rmqueue()函数从伙伴系统分配并分解重排内存分区。

如果当前伙伴系统中不能找到足够的空闲页内存~那么内核将采取的动作是:失败的话就尝试慢速分配,一般流程就是唤醒内存页面回收线程,然后尝试低水位分配 -> 忽略水位分配 -> 压缩内存分配 -> 直接回收内存分配 -> oom killer杀死线程分配 -> 压缩内存分配。

时间: 2024-10-10 15:08:48

[linux内存]伙伴系统学习笔记(三)--分配器API的相关文章

[linux内存]伙伴系统学习笔记(一)——概念

1,伙伴系统的作用: 伙伴系统主要是为了高效使用物理内存,尽量减少内存碎片的产生 2,伙伴系统的概念: 系统中的内存总是两两分组,每组中的两个内存块称为伙伴 3,伙伴系统的原理:  伙伴系统是相对于struct zone而言,将每个zone的空闲内存分为最多11个数组,比如第一个数组里管理着2^0页的内存,所有这些2^0的页以struct page的lru域的双向链表相连接,第二个数组管理着2^1页的内存,所有这些2^0的页以struct page的lru域的双向链表相连接,以此类推,.....

[linux内存]伙伴系统学习笔记(二)--内存系统初始化

1,本文大部分来自:http://blog.csdn.net/vanbreaker/article/details/7611585 2,在start_kernel()-->paging_init()-->zone_sizes_init()-->free_area_init_nodes()-->free_area_init_node()-->free_area_init_core()-->init_currently_empty_zone()->zone_init_

Linux内存管理学习笔记——内存寻址

最近开始想稍微深入一点地学习Linux内核,主要参考内容是<深入理解Linux内核>和<深入理解Linux内核架构>以及源码,经验有限,只能分析出有限的内容,看完这遍以后再更深入学习吧. 1,内存地址 逻辑地址:包含在机器语言中用来指定一个操作数或一条指令的地址. 线性地址:一个32位无符号数,用于直接映射物理地址 物理地址:片上引脚寻址级别的地址 2,逻辑地址->线性地址 2.1 段选择符与段寄存器 逻辑地址:段选择符(16位)+段内偏移(32位) index:在GDT或L

Linux内存管理学习笔记 转

https://yq.aliyun.com/articles/11192?spm=0.0.0.0.hq1MsD 随着要维护的服务器增多,遇到的各种稀奇古怪的问题也会增多,要想彻底解决这些“小”问题往往需要更深的Linux方面的知识.越专业.分工越细的工程师,在这方面的要求也就越高.这次,对MySQL Swap的问题的探索过程,就一不小心掉进了Linux Memory Managemant(Linux MM)的研究中去了,爬了很久才出来,这里做一个系列笔记. 笔记中很多内容都是参考<Underst

[linux驱动][Linux内存]DMA学习笔记一

http://www.cnblogs.com/hanyan225/archive/2010/10/28/1863854.html 1,概念DMA是一种无须CPU的参与就可以让外设与系统内存之间进行双向数据传输的硬件机制.使用DMA可以是系统CPU从实际的IO数据传输过程中摆脱出来,从而大大提供系统吞吐率.DMA方式的数据传输由DMA控制器(DMAC)控制,在传输期间,CPU可以并发地执行其他任务,当DMA结束后,DMAC通过中断通知CPU数据传输已经结束,然后由CPU执行相应的中断服务程序进行后

[Linux内存]vmalloc学习笔记

一:vmallochttp://www.360doc.com/content/14/0614/13/18127083_386524093.shtml1,vmalloc()的内核入口函数是kernel/mm/Vmalloc.c里的void *vmalloc(unsigned long size),size表示的是请求内核分配的字节数目. [cpp] view plaincopy void *vmalloc(unsigned long size) { return __vmalloc_node_fl

Redis学习笔记(三) Redis API与常用数据类型简介

一.Redis中常用数据类型 由上一篇博客可知,Redis目前提供五种数据类型:string(字符串).list(链表).Hash(哈希).set(集合)及zset(sorted set)  (有序集合).现在,我们一一来看看这五种数据类型的基本使用方法.在开始介绍之前,我们先使用刚刚引入的Redis API建立一个Redis客户端对象,有了这个客户端对象,我们才能和Redis服务端进行通信,且看下面的一行代码.我们需要事先指定好Redis服务端的IP地址和端口号,然后根据这两个信息建立一个Re

Linux程序设计学习笔记----网络通信编程API及其示例应用

转载请注明出处, http://blog.csdn.net/suool/article/details/38702855. BSD Socket 网络通信编程 BSD TCP 通信编程流程 图为面向连接的Socket通信的双方执行函数流程.使用TCP协议的通信双方实现数据通信的基本流程如下 建立连接的步骤 1.首先服务器端需要以下工作: (1)调用socket()函数,建立Socket对象,指定通信协议. (2)调用bind()函数,将创建的Socket对象与当前主机的某一个IP地址和TCP端口

Linux System Programming 学习笔记(九) 内存管理

1. 进程地址空间 Linux中,进程并不是直接操作物理内存地址,而是每个进程关联一个虚拟地址空间 内存页是memory management unit (MMU) 可以管理的最小地址单元 机器的体系结构决定了内存页大小,32位系统通常是 4KB, 64位系统通常是 8KB 内存页分为 valid or invalid: A valid page is associated with an actual page of data,例如RAM或者磁盘上的文件 An invalid page is