物理内存的组织方式

  • 物理内存是由连续的一页一页的块组成,每个物理页都有页号
  • 每个页由struct page表示,放进数组里——平坦内存模型

SMP和NUMA

  • SMP中,总线会称为瓶颈,因为数据都要经过它
  • NUMA中
    • 每个CPU都有本地内存,CPU访存不用过总线
    • 但本地内存不足时,每个CPU可以去另外的NUMA节点申请内存,延时较长
    • NUMA基本是非连续内存模型,非连续内存模型不一定就是NUMA
typedef struct pglist_data
{
struct zone node_zones[MAX_NR_ZONES]; // 每个节点还会分成一个个区域zone
struct zonelist node_zonelists[MAX_ZONELISTS]; // 备用节点
int nr_zones;
struct page *node_mem_map; // 此节点的struct page数组
unsigned long node_start_pfn; // 起始页号
unsigned long node_present_pages; /* total number of physical pages */
unsigned long node_spanned_pages; /* total size of physical page range, including holes */
int node_id; // 自己的id
......
} pg_data_t;

举个例子:

64M 物理内存隔着一个 4M 的空洞,然后是另外的 64M 物理内存。 换算成页面数目就是,16K 个页面隔着 1K 个页面,然后是另外 16K 个页面。这种情况下,node_spanned_pages 就是 33K 个页面,node_present_pages 就是 32K 个页面。

ZONE_DMA

ZONE_DMA可用于做直接内存存取的内存。

DMA机制:

要把外设的数据读入内存或把内存的数据传送到外设,原来都要通过 CPU 控制完成,但是这会占用 CPU,影响 CPU 处理其他事情,所以有了 DMA 模式。CPU 只需向 DMA 控制器下达指令,让 DMA 控制器来处理数据的传送,数据传送完毕再把信息反馈给 CPU,这样就可以解放 CPU。

64位系统有两个DMA系统,除了ZONE_DMA还有ZONE_DMA32

区域

上面把内存分成了节点,把节点分成了区域。区域zone的定义:

struct zone {
......
struct pglist_data *zone_pgdat;
struct per_cpu_pageset __percpu *pageset; // 用于区分冷热页 unsigned long zone_start_pfn; // 表示属于这个zone的第一页 /*
* spanned_pages is the total pages spanned by the zone, including
* holes, which is calculated as:
* spanned_pages = zone_end_pfn - zone_start_pfn;
*
* present_pages is physical pages existing within the zone, which
* is calculated as:
* present_pages = spanned_pages - absent_pages(pages in holes);
*
* managed_pages is present pages managed by the buddy system, which
* is calculated as (reserved_pages includes pages allocated by the
* bootmem allocator):
* managed_pages = present_pages - reserved_pages;
*
*/
unsigned long managed_pages; // 此zone被伙伴系统管理的所有page数目
unsigned long spanned_pages; // 包括中间的物理内存空洞
unsigned long present_pages; // 物理内存中真实存在的page数 const char *name;
......
/* free areas of different sizes */
struct free_area free_area[MAX_ORDER]; /* zone flags, see below */
unsigned long flags; /* Primarily protects free_area */
spinlock_t lock;
......
} ____cacheline_internodealigned_in_

什么是冷热页?

x86 体系结构中,为了让 CPU 快速访问段描述符,在 CPU 里面有段描述符缓存。CPU 访问这个缓存的速度比内存快得多。同样对于来讲,也是这样的。如果一个页被加载到 CPU 高速缓存里面,这就是一个热页(Hot Page),CPU 读起来速度会快很多,如果没有就是冷页(Cold Page)。由于每个 CPU 都有自己的高速缓存,因而 per_cpu_pageset 也是每个 CPU 一个。

页(Page)

一个物理页面可以使用多种模式:

  • 要用就用一整页

    • 匿名页:一整页的内存,或者直接和虚拟地址空间建立映射关系
    • 内存映射文件:或者用于关联一个文件,然后再和虚拟地址空间建立映射关系
    • 每个进程都有自己的页表
  • 仅需分配小块内存
    • Linux采用了slab allocator 的技术,用于分配称为slab的小块内存
    • 基本原理:
      • 从内存管理模块申请一整块页
      • 划分成多个小块的存储池,用复杂的队列维护小块的状态
      • 状态包括:被分配了/被放回池子/应该被回收

Linux中把所有空闲页分为了11个页块链表,每个块链表分别包含很多个大小的页块,有1、2、4、8、16、32、64、128、512和1024个连续的页块。

请求分配页块时,依次按照更大的页块链表去找。分配的页块有多余的页时,伙伴系统会根据多余的页块大小,插入到对应的空闲页块链表中。

举个栗子:

要请求一个 128 个页的页块时,先检查 128 个页的页块链表是否有空闲块。如果没有,则查 256 个页的页块链表;如果有空闲块的话,则将 256 个页的页块分成两份,一份使用,一份插入 128 个页的页块链表中。如果还是没有,就查 512 个页的页块链表;如果有的话,就分裂为 128、128、256 三个页块,一个 128 的使用,剩余两个插入对应页块链表。

小结

  • 如果有多个 CPU,那就有多个节点。每个节点用 struct pglist_data 表示,放在一个数组里面。
  • 每个节点分为多个区域,每个区域用 struct zone 表示,也放在一个数组里面。
  • 每个区域分为多个页。为了方便分配,空闲页放在 struct free_area 里面,使用伙伴系统进行管理和分配,每一页用 struct page 表示。

Linux — 物理内存管理的更多相关文章

  1. 一步一图带你深入理解 Linux 物理内存管理

    1. 前文回顾 在上篇文章 <深入理解 Linux 虚拟内存管理> 中,笔者分别从进程用户态和内核态的角度详细深入地为大家介绍了 Linux 内核如何对进程虚拟内存空间进行布局以及管理的相 ...

  2. linux物理内存管理

    1.为什么需要连续的物理内存: Linux内核管理物理内存是通过分页机制实现的,它将整个内存划分成无数个4k(在i386体系结构中)大小的页,从而分配和回收内存的基本单位便是内存页了.利用分页管理有助 ...

  3. 深入理解 Linux 物理内存分配全链路实现

    前文回顾 在上篇文章 <深入理解 Linux 物理内存管理>中,笔者详细的为大家介绍了 Linux 内核如何对物理内存进行管理以及相关的一些内核数据结构. 在介绍物理内存管理之前,笔者先从 ...

  4. Linux内存管理 (1)物理内存初始化

    专题:Linux内存管理专题 关键词:用户内核空间划分.Node/Zone/Page.memblock.PGD/PUD/PMD/PTE.lowmem/highmem.ZONE_DMA/ZONE_NOR ...

  5. LInux中的物理内存管理

    2017-02-23 一.伙伴系统 LInux下用伙伴系统管理物理内存页,伙伴系统得益于其良好的算法,一定程度上可以避免外部碎片为何这么说?先回顾下Linux下虚拟地址空间的分布. 在X86架构下,系 ...

  6. Linux内存:物理内存管理概述

    内存中的物理内存管理 概述 一般来说,linux内核一般将处理器的虚拟地址空间划分为2部分.底部比较大的部分用于用户进程,顶部则专用于内核. 在IA-32系统上,地址空间在用户进程和内核之间划分的典型 ...

  7. 浅谈Linux内存管理机制

    经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...

  8. linux内存管理

    一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程 ...

  9. Linux内存管理原理

    本文以32位机器为准,串讲一些内存管理的知识点. 1. 虚拟地址.物理地址.逻辑地址.线性地址 虚拟地址又叫线性地址.linux没有采用分段机制,所以逻辑地址和虚拟地址(线性地址)(在用户态,内核态逻 ...

  10. 了解linux内存管理机制(转)

    今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...

随机推荐

  1. Apache服务器打开网页是乱码解决方案

    当 Apache 服务器显示乱码时,可以使用两种方法解决: 1. 服务器端 可以在 Apache 的配置文件中添加以下内容来设置默认编码为UTF-8: AddDefaultCharset utf-8 ...

  2. S锁,X锁,乐观锁和悲观锁

    S锁:S锁也叫共享锁,读锁,数据只能被读取不能被修改. X锁:X锁也叫排他锁,写锁,一个事务对表加锁后,其他事务就不能对其进行加锁与增删查改操作. 乐观锁:总是假设是最好的情况,每次去操作的时候都不会 ...

  3. #dp#洛谷 4399 [JSOI2008]Blue Mary的职员分配

    题目 分析 设\(dp[i][day][j][k]\)表示当前雇员个数为\(i\), 距离上次发广告时间为\(day\),获得的金钱和声望分别为\(j,k\) 注意\(day\)是\([0\sim 3 ...

  4. OpenHarmony定义组件重用样式:@Styles装饰器

      如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器@Styles. @St ...

  5. OpenHarmony社区运营报告(2022年9月)

    篇首语 在开放原子开源基金会.OpenAtom OpenHarmony(简称"OpenHarmony")工作委员会.会员及共建单位和开发者的共同努力下,OpenHarmony在技术 ...

  6. Windows系统编译libhv带SSL,开启WITH_OPENSSL

    需要开发一个https的服务,使用libhv来做,需要重新编译libhv,需要开启 WITH_OPENSSL,前面编译一直很顺利,但是打开VS生成动态库的时候,报错,找不到ssl相关的文件,看了官方的 ...

  7. js 词法作用域

    前言 什么是作用域? 作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域. 白话文:作用域就是变量在哪块 ...

  8. 实时数仓构建:Flink+OLAP查询的一些实践与思考

    今天是一篇架构分享内容. 1.概述 以Flink为主的计算引擎配合OLAP查询分析引擎组合进而构建实时数仓,其技术方案的选择是我们在技术选型过程中最常见的问题之一.也是很多公司和业务支持过程中会实实在 ...

  9. 在windows电脑中安装redis

    1,github下载地址:https://github.com/MSOpenTech/redis/tags 2,下载完成后,解压到对应文件夹 3,打开redis.windows.conf,在#requ ...

  10. python数据库迁移

    实际操作命令 1,python 文件.py db init 2,python xx.py db migrate -m '版本描述' 3,python xx.py db upgrade 4,python ...