Linux内存管理 (一) 内存组织

内存管理是内核最复杂同时也是最重要的一部。其特点在于非常需要处理器和内核之间的协作。

首先内存划分为结点,在内核中表示为pg_data_t,每个结点划分为内存域。 

以下的所有数据结构或代码都做了不同程度的精减,一方面是为了保留相关代码,除去细枝末叶,另一方面是为了美观。 

结点的数据结构为


<mmzone.h>
typedef struct pglist_data {
struct zone node_zones[MAX_NR_ZONES]; /*内存结点所包含的内存域数组*/
struct zonelist node_zonelists[MAX_ZONELISTS]; /*指定了备用结点及其内存域列表*/
int nr_zones; /*内存域的数目*/
#ifdef CONFIG_FLAT_NODE_MEM_MAP
struct page *node_mem_map; /*node_mem_map是指向page实例数组的指针,它包含了结点中所有内存域的页*/
#endif
struct bootmem_data *bdata; /*bdata指定了用于自举分配器数据结构的实例*/
#ifdef CONFIG_MEMORY_HOTPLUG
#endif
unsigned long node_start_pfn; /*结点内第一个页帧的逻辑编号*/
unsigned long node_present_pages; /* 物理内存页的总数,不包括内存洞 */
unsigned long node_spanned_pages; /* 物理内存页的总长度,包括洞在内 */
int node_id; /*结点id*/
  struct pglist_data *pgdata_next; /*下一个内存结点的指针*/
} pg_data_t;

内存域是由枚举来表示的,如下所示


<mmzone.h>
enum zone_type {
#ifdef CONFIG_ZONE_DMA
ZONE_DMA,/*ZONE_DMA表示DMA区域。在IA-32机器上,一般的限制是0~16M。*/
#endif   
ZONE_NORMAL,/*ZONE_NORMAL表示可直接映射到内核段的普通内存域。在x86机器上为16M~896M.*/
#ifdef CONFIG_HIGHMEM
ZONE_HIGHMEM,/* ZONE_HIGHMEM标记了超出内核段的物理内存。如在x86机器上,内存为4G,那么896M~4G就为高端内存。*/
#endif
ZONE_MOVABLE, /* ZONE_MOVABLE表示的内存域属于伪内存域,主要用于防止内存碎片。*/  
MAX_NR_ZONES/*MAX_NR_ZONES充当结束标记。用于内存域的迭代。*/
};

内存域的结构描述如下:


<mmzone.h>
struct zone {
  /*
   *pages_min, pages_low, pages_high是水印,用于面换出时的计算
   *pages_high表示如果内存域中的空闲页多于此值,则内存域的状态是理想的
   *pages_low表示如果内存域中的空闲页低于此值,则内核开始将页换出到硬盘
   *pages_min表示如果内存域中的空闲页低于此值,则表示空闲页极少。此时页回收工作压力很大。
   */
  unsigned long pages_min, pages_low, pages_high;
  /*
   *lowmen_reserve表示为各个内存域预留的页数目,用于不能失败的关键性内存分配
   */
  unsigned long lowmem_reserve[MAX_NR_ZONES];

struct per_cpu_pageset pageset[NR_CPUS]; /* 每个CPU的冷热帧列表*/

spinlock_t lock; /*自旋锁*/
  struct free_area free_area[MAX_ORDER];/*用于伙伴系统的数据结构*/

spinlock_t lru_lock; /*自旋锁*/
struct list_head active_list; /*活动页的集合,page实例*/
struct list_head inactive_list; /*不活动页的集合, page实例*/
unsigned long nr_scan_active;/*指定回收内存时需要扫描的活动页的数目*/
unsigned long nr_scan_inactive;/*指定回收内存时需要扫描的不活动页的数目*/
unsigned long pages_scanned; /* 指定了上一欠掏出一页以来,有多少页未能成功扫描*/
unsigned long flags; /* 内存域的当前状态 */

atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; /*内存的统计信息*/

struct pglist_data *zone_pgdat; /*指定pg_data_t实例*/
/* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
unsigned long zone_start_pfn; /*内存域的第一个页帧的索引*/
};

页帧的数据结构:


struct page {
unsigned long flags; /* 页帧的标记*/
atomic_t _count; /* 使用记数 */
union {
atomic_t _mapcount; /*内存管理子系统中映射的页表项计数,用于表示页是否已经映射,还用于限制逆向映射搜索*/
unsigned int inuse; /* 用于SLUB分配器:对象的数目*/
};
union {
struct {
unsigned long private; /* 由映射私有,不透明数据*/
struct address_space *mapping; /*映射所在的地址空间*/
};
     struct kmem_cache *slab; /* 指向slub的指针 */
struct page *first_page; /* 用于复合页的尾页,指向首页 */
};
union {
pgoff_t index; /* 在映射内的偏移量 */
void *freelist; /* SLUB: freelist req. slab lock */
};
struct list_head lru; /*用于在各种不同的鍡上维护该页*/
  
#if defined(WANT_PAGE_VIRTUAL)
void *virtual; /*用于高端内存中的页。存储该页的虚拟地址*/
#endif /* WANT_PAGE_VIRTUAL */
};

Linux内存管理 (一) 内存组织,布布扣,bubuko.com

时间: 2025-01-02 00:10:24

Linux内存管理 (一) 内存组织的相关文章

内存管理:内存泄漏和空悬指针

********内存管理基础********************* 内存管理:针对的是实例的内存占用的管理(放在堆里面) 实例:1:由class类型构建的实例,2:闭包对象 内存管理技术:ARC:Automatic Reference Count 自动:由语言本身帮我们销毁内存,不需要你手动销毁, 比如在c中就调用dealloc() 引用:let p = Person()  p就是对Person()这个对象的一个引用 计数: let p = Person() //一个 / / let pp

java基础---JVM内存管理以及内存运行机制学习总结

自己从网上搜资料拼接了一张JVM内存图:如下图所示: 我们思考几个问题: 1.jVM是怎么运行的? 2.JVM运行时内存是怎么分配的? 3.我们写的java代码(类,对象,方法,常量,变量等等)最终存放在哪个区? VM运行时数据区域: 1.程序计数器(program Counter Register):   是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里(仅是概念模型,各种虚拟机可能会通过一些更高效的 方式去实 现),字节码解释器工作时就是通过改

内存管理之内存池概述(转)

原文链接:http://www.xiaoyaochong.net/wordpress/index.php/2013/08/10/%E5%BC%95%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E4%B9%8B%E5%86%85%E5%AD%98%E6%B1%A0%E6%A6%82%E8%BF%B0/ 在我们编写代码的过程中,不可避免的要和内存打交道,在申请释放不太频繁的情况下,通常让系统进行内存管理即可.但是,直接使用系统调用malloc/free.new/delet

Objective-C 【内存管理&amp;手动内存管理 综述】

------------------------------------------- 内存管理 (1)Objective-C的内存管理 栈区    存放局部变量(由于基本数据类型占用的存储空间是固定的,由系统去分配,我们不用去管,故栈区存放基本数据类型,) 堆区    存放程序运行过程中动态分配的内存空间(对象类型是程序运行过程中动态分配的,他们的大小不固定.比如说是我们Person new申请来的,存放在堆区,也是我们需要管理的) ★所以内存管理的范围是   继承了NSObject的所有对象

第九讲.内存管理初级.(内存管理的方式,引用计数机制及影响计数的各个方法,dealloc方法,内存管理的基本原则,掌握copy的实现)

一.内存管理的方式. 1.进行内存管理的原因: 1>.由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等. 管理范围:任何继承NSObject的对象,对其他的基本数据类型无效. 2>.本质原因是因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指

内存管理 浅析 内存管理/内存优化技巧

内存管理 浅析 下列行为都会增加一个app的内存占用: 1.创建一个OC对象: 2.定义一个变量: 3.调用一个函数或者方法. 如果app占用内存过大,系统可能会强制关闭app,造成闪退现象,影响用户体验.如何让回收那些不再使用的对象呢?本文着重介绍OC中的内存管理. 所谓内存管理,就是对内存进行管理,涉及的操作有: 1.分配内存:比如创建一个对象,会增加内存占用: 2.清除内存:比如销毁一个对象,会减少内存占用. 内存管理的管理范围: 1.任何继承了NSObject的对象: 2.对其他非对象类

Java的内存管理与内存泄露

作为Internet最流行的编程语言之一,Java现正非常流行.我们的网络应用程序就主要采用Java语言开发,大体上分为客户端.服务器和数据库三个层次.在进入测试过程中,我们发现有一个程序模块系统内存和CPU资源消耗急剧增加,持续增长到出现java.lang.OutOfMemoryError为止.经过分析Java内存泄漏是破坏系统的主要因素.这里与大家分享我们在开发过程中遇到的Java内存泄漏的检测和处理解决过程. 本文先介绍Java的内存管理,以及导致Java内存泄露的原因. 一. Java是

内存管理--检测内存

linux kernel被bootloader加载到内存后,cpu首先执行head.s中的start_of_setup函数等函数,然后跳转到main.c,main中首先执行detect_memory函数探测内存: int detect_memory(void) { int err = -1; if (detect_memory_e820() > 0) err = 0; if (!detect_memory_e801()) err = 0; if (!detect_memory_88()) err

浅谈C语言内存管理、内存泄露、堆栈

1.内存分配区间: 对于一个C语言程序而言,内存空间主要由五个部分组成:代码段(.text).数据段(.data).静态区(.BSS).堆和栈组成. BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量和静态变量 (这里注意一个问题:一般的书上都会说全局变量和静态变量是会自动初始化的,那么哪来的未初始化的变量呢?变量的初始化可以分为显示初始化和隐式初始化,全局变量和静态变量如果程序员自己不初始化的话的确也会被初始化,那就是不管什么类型都初始化为0,这种没有显示初始