《Linux源码情景分析》--2.1 Linux内存管理的基本框架

2.1 Linux内存管理的基本框架

? Linux内核的设计要考虑在各种不同的CPU上的实现,还要考虑64位CPU,所以不能仅仅针对i386结构来设计它的映射机制,要以一种假象的、虚拟的CPU和MMU(内存管理单元)为基础,设计出一种通用模型。在32位的内存空间下,两层映射系统比较有效,但是在64位内存空间下,两层映射会降低内存空间的效率。因此,Linux内核的映射机制设置为三层,在页面目录和页面表之间加入了一层“中间目录”。PGD、PMD、PT均为数组。相应的,在逻辑上也把线性地址从高到低划分为4个位段,分别用作目录PGD中下标、中间目录PMD中的下标、页面表中的下标、以及物理页面内的位移。

? 但是,这个虚拟的映射模型必须落实到具体的CPU和MMU物理映射机制。这里主要介绍了32位地址的二层映射:

#define PGDIR_SHIFT 22  //线性地址中PGD下标的起始位置,PGD位于线性地址的最高字段,因此PGD位22位到31位,一共10位。
#define PTRS_PER_PGD 1024  //PGD表中指针的个数位1024个,2的10次方。在32位系统中指针大小为4字节,因此PGD表大小4KB

/*
 * The i386 is two-level,so wo don't really have any
 * PMD direcotary physically.
 */

#define PMD_SHIFT 22 //PMD下标起始位置也为22,表示PMD长度为0。每个PMD表项的大小和PGD是一样的。
#define PTRS_PER_PMD 1 //每个PMD表中只有一个PMD表项,只有一个PT表指针。

#define PTRS_PER_PTE 1024 

? 这样,上述的4步映射过程对于内核(软件)和i386MMU就成为:

  1. 内核为MMU设置好映射目录PGD,MMU用线性地址中的最高的那一个位段(10位)作为下标在PGD中找到的表项。该表项逻辑上指向一个中间目录PMD,但是物理位置上直接指向相应的页表,MMU并不知道PMD的存在。
  2. PMD只是逻辑上存在,既对内核软件概念上的存在,但是表中只有一个表项,而所谓的映射就是保持原值不变;现在一转手却指向页表了。
  3. 内核为MMU设置好了所有的页面表,MMU用线性地址中的PT位段作为下标在相应页面表中找到相应的表项PTE,该表项中存放的就是指向物理页面的指针。
  4. 线性地址中最后位段为物理页面内的相对位移量,MMU将此位移量与物理页面的起始地址相加便得到相应的物理地址。

? 32位地址意味着4G字节的虚拟空间,Linux内核将最高的1G(虚地址 0xC0000000~0xFFFFFFFF)用于内核本身,称为“系统空间”,剩下的3G的空间(虚地址 0x0~0xBFFFFFFF)用作各个进程的“用户空间”。

? 虽然系统空间占据了最高的1G空间,但是物理的内存总是从最低的地址开始。因此,对于内核来说,其地址的映射是简单的线性映射:

#define __PAGE_OFFSET (0xC0000000)

#define PAGE_OFFSET   ((unsigned long)__PAGE_OFFSET)
#define __pa(x)       ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x)       ((void *)((unsigned long)(x)+PAGE_OFFSET))

? 每个进程都有自己的页面目录表PGD,在切换进程时也要将进程的PGD加载到CR3寄存器中,而内核记录的是PGD的虚拟地址,CR3需要的是物理地址,这时候就要用到__pa()了:

asm volatile("movl %0,%%cr3": :"r"(__pa(next->pgd)));//next->pgd 表示下一个进程的页面目录起始地址。

原文地址:https://www.cnblogs.com/LiShiZhen/p/11494448.html

时间: 2024-08-28 00:45:59

《Linux源码情景分析》--2.1 Linux内存管理的基本框架的相关文章

Linux内核源码情景分析-系统调用

一.系统调用初始化 void __init trap_init(void) { ...... set_system_gate(SYSCALL_VECTOR,&system_call);//0x80 ...... } 对0x80中断向量.设置了系统调用的总入口system_call. static void __init set_system_gate(unsigned int n, void *addr) { _set_gate(idt_table+n,15,3,addr); } 在IDT中设置

Linux 内核源码情景分析 chap 2 存储管理 (四)

物理页面的使用和周转 1. 几个术语 1.1 虚存页面 指虚拟地址空间中一个固定大小, 边界与页面大小 4KB 对齐的区间及其内容 1.2 物理页面 与虚存页面相对的, 须要映射到某种物理存储介质上面的页面. 依据他是否在内存中. 我们能够分为 内存页面 和 盘上页面. 另外. 通常说物理内存页面的分配和释放是指 物理介质, 而谈及页面的换入和换出的时候, 是指他的内容. 1.3 交换技术 当系统内存不够用的时候,我们能够把临时不用的信息 放到磁盘上, 为其它急用的信息腾出空间, 到须要的时候,

读android系统源码情景分析笔记(一)

android2.3系统驱动模块由内核模块,硬件抽象模块,用户调用模块(jni)组成,内核模块和linux一致,硬件抽象模块主要需要定义两个结构:hw_module_t和hw_device_t. hw_module_t包含模块id,版本号,署名和一个函数指针: int open (struct hw_module_t* module, const char* id, struct hw_device_t** device); hw_device_t包含版本,hw_module_t的引用和一个函数

Nginx源码研究二:NGINX的内存管理

关于nginx的内存使用,我们先看代码,下面是nginx_cycle.c中对全局数据结构cycle的初始化过程 pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); //申请16K的内存池 if (pool == NULL) { return NULL; } pool->log = log; cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); if (cycle == NULL) { ngx_destroy

从linux源码看epoll

从linux源码看epoll前言在linux的高性能网络编程中,绕不开的就是epoll.和select.poll等系统调用相比,epoll在需要监视大量文件描述符并且其中只有少数活跃的时候,表现出无可比拟的优势.epoll能让内核记住所关注的描述符,并在对应的描述符事件就绪的时候,在epoll的就绪链表中添加这些就绪元素,并唤醒对应的epoll等待进程.本文就是笔者在探究epoll源码过程中,对kernel将就绪描述符添加到epoll并唤醒对应进程的一次源码分析(基于linux-2.6.32内核

linux源码分析之字节序(5)-- swab.h

在linux源码分析之字节序(3).linux源码分析之字节序(4)中都有看到,源码中包含了 #include <linux/swab.h> 该头函数里面介绍了字节交换的具体方法.我们来看看具体代码: --------------------------------------------------------------------------------------------------------------- #ifndef _LINUX_SWAB_H #define _LINUX

linux源码分析之字节序(2)-- types.h

这一节主要讲linux的数据类型,主要是为了方便理解接下来将大端.小段字节序定义的源码. 首先,来看看 include/linux/types.h 源码: ------------------------------------------------------------------ #ifndef _LINUX_TYPES_H #define _LINUX_TYPES_H #include <asm/types.h> #ifndef __ASSEMBLY__ #include <l

linux源码分析之字节序(4)-- little_endian.h

本节主要分析小端字节顺序. 首先,我们要回顾上一节讲过的大端.小端的概念: 字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端.大端两种字节顺序.小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处:大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处.基于X86平台的PC机是小端字节序的,而有的嵌入式平台则是大端字节序的.因而对int.uint16.uint32等多于1字节类型的数据,在这些嵌入式平台上应该变换其存储顺序.通常我们认为,在空中传输

Linux内核源代码情景分析系列

http://blog.sina.com.cn/s/blog_6b94d5680101vfqv.html Linux内核源代码情景分析---第五章 文件系统 5.1 概述 构成一个操作系统最重要的就是 进程管理 与 文件系统: 有些操作系统有进程管理而没有文件系统,有些操作系统有文件系统而没有进程管理(MSDOS):两者都没有那就不是操作系统了: 狭义的文件:指磁盘文件,进入指可以是有序地存储在任何介质中(包括内存)的一组信息. 广义的文件:(unix把外部设备也当成文件)凡是可以产生或消耗信息