关键词:
13. 内存管理
#define NODES_SHIFT CONFIG_NODES_SHIFT
#define MAX_NUMNODES (1 << NODES_SHIFT)
这里主要介绍UMA机制。contig_page_data被定义如下:
struct pglist_data __refdata contig_page_data = { .bdata = &bootmem_node_data[0] };
EXPORT_SYMBOL(contig_page_data);
struct pglist_data即是pg_data_t的原型。了解pg_data_t中的结构成员对于了解内存管理是必经之路:
struct zone node_zones[MAX_NR_ZONES];
struct zonelist node_zonelists[MAX_ZONELISTS];
#ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */
#ifdef CONFIG_CGROUP_MEM_RES_CTLR
struct page_cgroup *node_page_cgroup;
...... /* for CONFIG_MEMORY_HOTPLUG */
unsigned long node_present_pages; /* total number of physical pages */
unsigned long node_spanned_pages; /* total size of physical page
wait_queue_head_t kswapd_wait;
- node_zones:当前节点中包含的最大管理区数。MAX_NR_ZONES在include/linux/bounds.h定义,该文件是在编译过程中根据管理区类型定义中的__MAX_NR_ZONES变量自动生成的。
- node_zonelists: 内存分配器所使用的管理区链表数组,MAX_ZONELISTS的值在配置CONFIG_NUMA时为2,否则为1。索引为0的链表表示后援 (Fallback)链表,也即当该链表中的第一个不满足分配内存时,依次尝试链表的其他管理区。索引为1,的链表则用来针对GFP_THISNODE的 内存申请,此时只能申请指定的该链表中的管理区。
- nr_zones:指定当前节点中的管理区数,也即node_zones中实际用到的管理区数。它的取值范围为[1, MAX_NR_ZONES]。对于UMA来说,它的值为1。
- node_mem_map:节点中页描述符数组首地址。
- node_page_cgroup:
- bdata:系统引导时用的Bootmem分配器。
- node_start_pfn:节点中第一个页框的下标。
- node_present_pages:节点中的页面数,不包含孔洞。
- node_spanned_pages:节点中的页面总数,包含孔洞。
- node_id:节点标识符,在节点数组中唯一存在。
- kswapd_wait:kswapd页换出守护进程使用的等待队列。
- kswapd: 指针指向kswaps内核线程的进程描述符。
- kswapd_max_order:kswapd将要创建的空闲块大小取对数的值。
/* Maximum number of zones on a zonelist */
#define MAX_ZONES_PER_ZONELIST (MAX_NUMNODES * MAX_NR_ZONES)
struct zonelist_cache *zlcache_ptr; // NULL or &zlcache
struct zoneref _zonerefs[MAX_ZONES_PER_ZONELIST + 1];
struct zonelist_cache zlcache; // optional ...
节点中的管理区都在free_area_init_core函数中初始化。调用关系如下所示:
最后一种限制不仅存在于80x86,而存在于所有的体系结构中。为了应对这两种限制,Linux把每个内存节点的物理内存划分为多个(通常为3个)管理区(zone)。在80x86 UMA体系结构中的管理区为:
/* Fields commonly accessed by the page allocator */
unsigned long pages_min, pages_low, pages_high;
unsigned long lowmem_reserve[MAX_NR_ZONES];
struct per_cpu_pageset pageset[NR_CPUS];
struct free_area free_area[MAX_ORDER];
/* Fields commonly accessed by the page reclaim scanner */
unsigned long recent_rotated[2];
unsigned long recent_scanned[2];
unsigned long pages_scanned; /* since last reclaim */
unsigned long flags; /* zone flags, see below */
atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
- pages_min,记录管理区中空闲页的数目。
- pages_low,回收页框使用的下届,同时也被管理区分配器作为阈值使用。
- pages_high,回收页框使用的上届,同时也被管理区分配器作为阈值使用。
- lowmem_reserve,指明在处理内存不足的临界情况下每个管理区必须保留的页框数目。
- pageset,单一页框的特殊告诉缓存。
内核为了尽可能保证一个原子内存分配请求成功,它为原子内存分配请求保留了一个页框池,只有在内存不足时才使用。保留内存的数量存放在min_free_kbytes变量中,单位为KB。
/* min_free_kbytes = sqrt(lowmem_kbytes * 16); */
lowmem_kbytes = nr_free_buffer_pages() * (PAGE_SIZE >> 10);
min_free_kbytes = int_sqrt(lowmem_kbytes * 16);
名称 | 大小 |
pages_min | min_free_kbytes >> (PAGE_SHIFT - 10) |
pages_low | pages_min * 5 / 4 |
pages_high | pages_min * 3 / 2 |
free_area_init_core中对管理区初始化的代码部分如下,后续章节将对该函数进一步分析。
zone->present_pages = realsize;
spin_lock_init(&zone->lru_lock);
zone->prev_priority = DEF_PRIORITY;
INIT_LIST_HEAD(&zone->lru[l].list);
unsigned long flags; /* Atomic flags, some possibly
atomic_t _count; /* Usage count, see below. */
atomic_t _mapcount; /* Count of ptes mapped in mms,
* & limit reverse map searches.
每一个物理页框都需要一个对应的page结构来进行管理:记录分配状态,分配和回收,互斥以及同步操作。对该结构成员的解释如下:
- flag域存放当前页框的页标志,它存储了体系结构无关的状态,专门供Linux内核自身使用。该标志可能的值定义在include/linux/page-flags.h中。
- 原子计数成员_count则指明了当前页框的引用计数,当该值为0时,就说明它没有被使用,此时在新分配内存时它就可以被使用。内核代码应该通过page_count来访问它,而非直接访问。
- 原子计数成员_mapcount表示在页表中有多少页指向该页框。在SLUB中它被inuse和objects代替。
PG_locked, /* Page is locked. Don't touch. */
以上是页标志位的可能取值,通常不应该直接使用这些标志位,而应该内核预定义好的宏,它们在相同的头文件中被定义,但是它们是被间接定义的,也即通过##连字符来统一对它们进行定义。
#define TESTPAGEFLAG(uname, lname) \
static inline int Page##uname(struct page *page) \
{ return test_bit(PG_##lname, &page->flags); }
PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced)
宏 | 扩展函数/宏 | 用途 |
TESTPAGEFLAG(uname, lname) | Page##uname | 测试PG_##lname位 |
SETPAGEFLAG(uname, lname) | SetPage##uname | 设置PG_##lname位 |
CLEARPAGEFLAG(uname, lname)[a] | ClearPage##uname | 清除PG_##lname位 |
TESTSETFLAG(uname, lname) | TestSetPage##uname | 测试并设置PG_##lname |
TESTCLEARFLAG(uname, lname) | TestClearPage##uname | 测试并清除PG_##lname |
PAGEFLAG(uname, lname)[b] | TESTPAGEFLAG | 当于同时扩展了三个宏,也即三个函数 |
PAGEFLAG_FALSE(uname) | Page##uname | 永远返回0 |
TESTSCFLAG(uname, lname) | TESTSETFLAG | 当于同时扩展了两个宏,也即两个函数 |
SETPAGEFLAG_NOOP(uname) | SetPage##uname | 空操作 |
CLEARPAGEFLAG_NOOP(uname) | ClearPage##unam | 空操作 |
__CLEARPAGEFLAG_NOOP(uname) | __ClearPage##uname | 空操作 |
TESTCLEARFLAG_FALSE(uname) | TestClearPage##uname | 永远返回0 |
[a] 以上三个宏分别对应test_bit,set_bit和clear_bit,是原子操作,与它们对应的是有三个开头 [b] 与此对应也有__PAGEFLAG的宏存在。 | :内存管理--内存管理的概念
1.内存管理的概念1.1内存空间的分配与回收1.2内存空间的扩充补充:操作系统的四大特性1.3地址转换转换的三种方式:转入内存的三种方式详解1.4存储保护1.5小结 查看详情 关于内存管理内存管理涉及根据数据库更改的需求为OracleDatabase实例内存结构维护最佳大小。必须管理的内存结构是系统全局区域(SGA)和实例程序全局区域(实例PGA)。Oracle数据库支持各种由初始化参数设置选择的内存管理方法。Oracle建议... 查看详情 rt-thread--内存管理(代码片段)内存管理的功能特点RT-Thread操作系统在内存管理上,根据上层应用及系统资源的不同,有针对性地提供了不同的内存分配管理算法。总体上可分为两类:内存堆管理与内存池管理,而内存堆管理又根据具体内存设备划分为三种情... 查看详情 内存管理与运行时所有运行时的内存管理都是针对虚拟内存进行管理的。 内存管理策略:1)手动管理:c、c++;2)引用计数;3)垃圾收集。 运行时管理策略: 手动管理:内存分散管理,随时释放; 引用计数:1)手动管理:计数为... 查看详情 stm32内存管理(代码片段)动态内存管理根据需要分配內存和回收内存通常在一块较大且连续的内存空间上进行分配和回收动态内存管理解决的问题内存资源稀缺,通过内存复用增加任务的并发性动态内存管理的本质时间换空间,通过动态分配和... 查看详情 内存管理作为一个JVM进程,EXecutor的内存管理建立在JVM的内存管理之上,Spark对JVM的对内空间进行了更为详细的分配,以充分利用内存。同时,Spark引入了堆外内存,使之可以直接在工作节点的系统内存中开辟空间,进一步优化内存的使用... 查看详情 操作系统-页式内存管理页式内存管理上A.段式内存管理1.指的是一段连续的内存空间2.段式内存管理-程序的各个部分相对独立(数据段,代码段),早期x86处理器无法通过一个寄存器访问所有内存单元,解决早期程序运行的重定位问题段式内存管理的应用... 查看详情 使用自动内存管理(代码片段)本节提供有关Oracle数据库的自动内存管理功能的背景信息,并包含有关启用此功能的说明。涵盖以下主题:关于自动内存管理启用自动内存管理监视和调整自动内存管理关于自动内存管理管理实例内存的最简单方法是让Oracle数据... 查看详情 操作系统内存管理1.内存管理方法 内存管理主要包含虚地址、地址变换、内存分配和回收、内存扩充、内存共享和保护等功能。 2.连续分配存储管理方式 连续分配是指为一个用户程序分配连续的内... 查看详情 内存管理技术任何语言都会涉及到内存的管理和使用,很多语言要求开发人员自己进行所有内存的管理工作,如c++等。而内存管理要求的技术难度很大,很多开发人员不能很好地完成,同时也成为意向沉重的负担。java则不同,其为内存管理... 查看详情 了解动态内存管理函数melloccallocfreerealloc,实现内存管理自由!(代码片段)动态内存管理笔记自取链接:动态内存管理笔记文章目录动态内存管理导言一、mallco开辟动态内存空间二、free释放动态内存空间三、calloc初始化+开辟动态内存空间四、realloc调整动态内存空间大小小结导言众所周知~,... 查看详情 linux操作系统原理—内存管理—页式内存管理技术目录文章目录目录虚拟内存技术页式内存管理技术虚拟内存技术虚拟内存技术是操作系统实现的一种高效的物理内存管理方式,具有以下作用:使得进程间彼此隔离:通过将物理内存和虚拟地址空间联系起来,并将虚拟地址空间... 查看详情 操作系统——内存管理:内存管理策略1.内存管理策略1.1背景1.1.1基本硬件1.1.2地址绑定1.1.3逻辑地址空间与物理地址空间1.1.4动态加载1.2交换1.3连续内存分配1.3.1内存保护1.3.2内存分配1.3.3内存碎片1.4分段1.5分页1.6页表结构1.6.1分层分页1.6.2哈希页表1.6.3倒置页表 计... 查看详情 spark从入门到精通spark内存管理详解-堆内&堆外内存管理前言Spark作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色。理解Spark内存管理的基本原理,有助于更好地开发Spark应用程序和进行性能调优。本文将详细介绍两部分内容,第一部分介绍Spa... 查看详情 linux内存管理子系统(概念入门)...模型Linux虚拟地址空间分布虚拟地址转化为物理地址物理内存分配大纲内存管理子系统内存管理模型地址映射管理物理地址分配管理子系统简介Linux内核系统构成管理模型Linux内存子系统管理模型上面的三个部分主要做物理内存分... 查看详情 linux内存管理子系统(概念入门)...模型Linux虚拟地址空间分布虚拟地址转化为物理地址物理内存分配大纲内存管理子系统内存管理模型地址映射管理物理地址分配管理子系统简介Linux内核系统构成管理模型Linux内存子系统管理模型上面的三个部分主要做物理内存分... 查看详情 sylixos定长内存管理1.定长内存管理介绍所谓定长内存,指的是用户每次分配获得的内存大小是相同的,即使用的是有确定长度的内存块。同时,这些内存块总的个数也是确定的,即整个内存总的大小也是确定的。这和通常理解的内存池的概念是一... 查看详情 ios中的内存管理(代码片段)在讲述iOS中的内存管理之前,先介绍一下其他语言中的内存管理,其实内存管理主要讲的是堆内存的管理,因为其他类型的内存,比如栈内存、全局变量/静态区内存、常量等各种语言的内存管理都差不多。Java中... 查看详情 |