成都公司注册代理,网站怎么seo关键词排名优化推广,什么软件可以做ppt,有服务器了怎么做网站由于物理地址是连续的#xff0c;页也是连续的#xff0c;每个页大小也是一样的。因而对于任何一个地址#xff0c;只要直接除一下每页的大小#xff0c;很容易直接算出在哪一页。每个页有一个结构 struct page 表示#xff0c;这个结构也是放在一个数组里面#xff0c;这…由于物理地址是连续的页也是连续的每个页大小也是一样的。因而对于任何一个地址只要直接除一下每页的大小很容易直接算出在哪一页。每个页有一个结构 struct page 表示这个结构也是放在一个数组里面这样根据页号很容易通过下标找到相应的 struct page 结构。
如果是这样整个物理内存的布局就非常简单、易管理这就是最经典的平坦内存模型Flat Memory Model。
在这种模式下CPU 也会有多个在总线的一侧。所有的内存条组成一大片内存在总线的另一侧所有的 CPU 访问内存都要过总线而且距离都是一样的这种模式称为 SMPSymmetric multiprocessing即对称多处理器。当然它也有一个显著的缺点就是总线会成为瓶颈因为数据都要走它。 为了提高性能和可扩展性后来有了一种更高级的模式NUMANon-uniform memory access非一致内存访问。在这种模式下内存不是一整块。每个 CPU 都有自己的本地内存CPU 访问本地内存不用过总线因而速度要快很多每个 CPU 和内存在一起称为一个 NUMA 节点。但是在本地内存不足的情况下每个 CPU 都可以去另外的 NUMA 节点申请内存这个时候访问延时就会比较长。
这样内存被分成了多个节点每个节点再被分成一个一个的页面。由于页需要全局唯一定位页还是需要有全局唯一的页号的。但是由于物理内存不是连起来的了页号也就不再连续了。于是内存模型就变成了非连续内存模型管理起来就复杂一些。
这里需要指出的是NUMA 往往是非连续内存模型。而非连续内存模型不一定就是 NUMA有时候一大片内存的情况下也会有物理内存地址不连续的情况。
当前的主流场景NUMA 方式。我们首先要能够表示 NUMA 节点的概念于是有了下面这个结构 typedef struct pglist_data pg_data_t它里面有以下的成员变量
每一个节点都有自己的 IDnode_idnode_mem_map 就是这个节点的 struct page 数组用于描述这个节点里面的所有的页node_start_pfn 是这个节点的起始页号node_spanned_pages 是这个节点中包含不连续的物理内存地址的页面数node_present_pages 是真正可用的物理页面的数目。
ZONE_DMA 是指可用于作 DMADirect Memory Access直接内存存取的内存。DMA 是这样一种机制要把外设的数据读入内存或把内存的数据传送到外设原来都要通过 CPU 控制完成但是这会占用 CPU影响 CPU 处理其他事情所以有了 DMA 模式。CPU 只需向 DMA 控制器下达指令让 DMA 控制器来处理数据的传送数据传送完毕再把信息反馈给 CPU这样就可以解放 CPU。
对于 64 位系统有两个 DMA 区域。除了上面说的 ZONE_DMA还有 ZONE_DMA32。在这里你大概理解 DMA 的原理就可以不必纠结我们后面会讲 DMA 的机制。
ZONE_NORMAL 是直接映射区就是上一节讲的从物理内存到虚拟内存的内核区域通过加上一个常量直接映射。
ZONE_HIGHMEM 是高端内存区就是上一节讲的对于 32 位系统来说超过 896M 的地方对于 64 位没必要有的一段区域。
ZONE_MOVABLE 是可移动区域通过将物理内存划分为可移动分配区域和不可移动分配区域来避免内存碎片。
为了让 CPU 快速访问段描述符在 CPU 里面有段描述符缓存。CPU 访问这个缓存的速度比内存快得多。同样对于页面来讲也是这样的。如果一个页被加载到 CPU 高速缓存里面这就是一个热页Hot PageCPU 读起来速度会快很多如果没有就是冷页Cold Page。由于每个 CPU 都有自己的高速缓存因而 per_cpu_pageset 也是每个 CPU 一个。
物理内存的基本单位页的数据结构 struct page。这是一个特别复杂的结构里面有很多的 unionunion 结构是在 C 语言中被用于同一块内存根据情况保存不同类型数据的一种方式。这里之所以用了 union是因为一个物理页面使用模式有多种。
第一种模式要用就用一整页。这一整页的内存或者直接和虚拟地址空间建立映射关系我们把这种称为匿名页Anonymous Page。或者用于关联一个文件然后再和虚拟地址空间建立映射关系这样的文件我们称为内存映射文件Memory-mapped File。
如果某一页是这种使用模式则会使用 union 中的以下变量
struct address_space *mapping 就是用于内存映射如果是匿名页最低位为 1如果是映射文件最低位为 0pgoff_t index 是在映射区的偏移量atomic_t _mapcount每个进程都有自己的页表这里指有多少个页表项指向了这个页struct list_head lru 表示这一页应该在一个链表上例如这个页面被换出就在换出页的链表中compound 相关的变量用于复合页Compound Page就是将物理上连续的两个或多个页看成一个独立的大页。
第二种模式仅需分配小块内存。有时候我们不需要一下子分配这么多的内存例如分配一个 task_struct 结构只需要分配小块的内存去存储这个进程描述结构的对象。为了满足对这种小内存块的需要Linux 系统采用了一种被称为 slab allocator 的技术用于分配称为 slab 的一小块内存。它的基本原理是从内存管理模块申请一整块页然后划分成多个小块的存储池用复杂的队列来维护这些小块的状态状态包括被分配了 / 被放回池子 / 应该被回收。
对于要分配比较大的内存例如到分配页级别的可以使用伙伴系统Buddy System。
Linux 中的内存管理的“页”大小为 4KB。把所有的空闲页分组为 11 个页块链表每个块链表分别包含很多个大小的页块有 1、2、4、8、16、32、64、128、256、512 和 1024 个连续页的页块。最大可以申请 1024 个连续页对应 4MB 大小的连续内存。每个页块的第一个页的物理地址是该页块大小的整数倍。 如果有多个 CPU那就有多个节点。每个节点用 struct pglist_data 表示放在一个数组里面。
每个节点分为多个区域每个区域用 struct zone 表示也放在一个数组里面。每个区域分为多个页。
为了方便分配空闲页放在 struct free_area 里面使用伙伴系统进行管理和分配每一页用 struct page 表示。 此文章为11月Day3学习笔记内容来源于极客时间《趣谈Linux操作系统》推荐该课程。