1 Pages

Page的概念来源为处理器Processor的部件MMU(Memory Management Unit),MMU通过设置好的页表(通过设置CR3寄存器,指向页目录所在的物理内存)对内存进行管理,管理操作包括:

a) 建立线性内存地址与物理内存地址的对应关系,即pa()和va()函数;

b) 管理哪些内存页驻存(Resident)于物理内存中,而哪些内存被交换到Swap文件中;

c) 哪些内存页被映射到哪个进程的虚拟地址空间;

d) 管理哪些内存页存储磁盘上(或者文件系统中)文件的缓存;

数据结构, struct page

   1: /*

   2:  * Each physical page in the system has a struct page associated with

   3:  * it to keep track of whatever it is we are using the page for at the

   4:  * moment. Note that we have no way to track which tasks are using

   5:  * a page, though if it is a pagecache page, rmap structures can tell us

   6:  * who is mapping it.

   7:  */

   8: struct page {

   9:     unsigned long flags;        /* Atomic flags, some possibly

  10:                      * updated asynchronously */

  11:     atomic_t _count;        /* Usage count, see below. */

  12:     union {

  13:         /*

  14:          * Count of ptes mapped in

  15:          * mms, to show when page is

  16:          * mapped & limit reverse map

  17:          * searches.

  18:          *

  19:          * Used also for tail pages

  20:          * refcounting instead of

  21:          * _count. Tail pages cannot

  22:          * be mapped and keeping the

  23:          * tail page _count zero at

  24:          * all times guarantees

  25:          * get_page_unless_zero() will

  26:          * never succeed on tail

  27:          * pages.

  28:          */

  29:         atomic_t _mapcount;

  30:  

  31:         struct {        /* SLUB */

  32:             u16 inuse;

  33:             u16 objects;

  34:         };

  35:     };

  36:     union {

  37:         struct {

  38:         unsigned long private;        /* Mapping-private opaque data:

  39:                           * usually used for buffer_heads

  40:                          * if PagePrivate set; used for

  41:                          * swp_entry_t if PageSwapCache;

  42:                          * indicates order in the buddy

  43:                          * system if PG_buddy is set.

  44:                          */

  45:         struct address_space *mapping;    /* If low bit clear, points to

  46:                          * inode address_space, or NULL.

  47:                          * If page mapped as anonymous

  48:                          * memory, low bit is set, and

  49:                          * it points to anon_vma object:

  50:                          * see PAGE_MAPPING_ANON below.

  51:                          */

  52:         };

  53: #if USE_SPLIT_PTLOCKS

  54:         spinlock_t ptl;

  55: #endif

  56:         struct kmem_cache *slab;    /* SLUB: Pointer to slab */

  57:         struct page *first_page;    /* Compound tail pages */

  58:     };

  59:     union {

  60:         pgoff_t index;        /* Our offset within mapping. */

  61:         void *freelist;        /* SLUB: freelist req. slab lock */

  62:     };

  63:     struct list_head lru;        /* Pageout list, eg. active_list

  64:                      * protected by zone->lru_lock !

  65:                      */

  66:     /*

  67:      * On machines where all RAM is mapped into kernel address space,

  68:      * we can simply calculate the virtual address. On machines with

  69:      * highmem some memory is mapped into kernel virtual memory

  70:      * dynamically, so we need a place to store that address.

  71:      * Note that this field could be 16 bits on x86 ... ;)

  72:      *

  73:      * Architectures with slow multiplication can define

  74:      * WANT_PAGE_VIRTUAL in asm/page.h

  75:      */

  76: #if defined(WANT_PAGE_VIRTUAL)

  77:     void *virtual;            /* Kernel virtual address (NULL if

  78:                        not kmapped, ie. highmem) */

  79: #endif /* WANT_PAGE_VIRTUAL */

  80: #ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS

  81:     unsigned long debug_flags;    /* Use atomic bitops on this */

  82: #endif

  83:  

  84: #ifdef CONFIG_KMEMCHECK

  85:     /*

  86:      * kmemcheck wants to track the status of each byte in a page; this

  87:      * is a pointer to such a status block. NULL if not tracked.

  88:      */

  89:     void *shadow;

  90: #endif

  91: };

每个page结构体对象,代表一个物理内存页。

x) flags

   1: enum pageflags {

   2:     PG_locked,        /* Page is locked. Don't touch. */

   3:     PG_error,

   4:     PG_referenced,

   5:     PG_uptodate,

   6:     PG_dirty,

   7:     PG_lru,

   8:     PG_active,

   9:     PG_slab,

  10:     PG_owner_priv_1,    /* Owner use. If pagecache, fs may use*/

  11:     PG_arch_1,

  12:     PG_reserved,

  13:     PG_private,        /* If pagecache, has fs-private data */

  14:     PG_private_2,        /* If pagecache, has fs aux data */

  15:     PG_writeback,        /* Page is under writeback */

  16: #ifdef CONFIG_PAGEFLAGS_EXTENDED

  17:     PG_head,        /* A head page */

  18:     PG_tail,        /* A tail page */

  19: #else

  20:     PG_compound,        /* A compound page */

  21: #endif

  22:     PG_swapcache,        /* Swap page: swp_entry_t in private */

  23:     PG_mappedtodisk,    /* Has blocks allocated on-disk */

  24:     PG_reclaim,        /* To be reclaimed asap */

  25:     PG_swapbacked,        /* Page is backed by RAM/swap */

  26:     PG_unevictable,        /* Page is "unevictable"  */

  27: #ifdef CONFIG_MMU

  28:     PG_mlocked,        /* Page is vma mlocked */

  29: #endif

  30: #ifdef CONFIG_ARCH_USES_PG_UNCACHED

  31:     PG_uncached,        /* Page has been mapped as uncached */

  32: #endif

  33: #ifdef CONFIG_MEMORY_FAILURE

  34:     PG_hwpoison,        /* hardware poisoned page. Don't touch */

  35: #endif

  36: #ifdef CONFIG_TRANSPARENT_HUGEPAGE

  37:     PG_compound_lock,

  38: #endif

  39:     __NR_PAGEFLAGS,

  40:  

  41:     /* Filesystems */

  42:     PG_checked = PG_owner_priv_1,

  43:  

  44:     /* Two page bits are conscripted by FS-Cache to maintain local caching

  45:      * state.  These bits are set on pages belonging to the netfs's inodes

  46:      * when those inodes are being locally cached.

  47:      */

  48:     PG_fscache = PG_private_2,    /* page backed by cache */

  49:  

  50:     /* XEN */

  51:     PG_pinned = PG_owner_priv_1,

  52:     PG_savepinned = PG_dirty,

  53:  

  54:     /* SLOB */

  55:     PG_slob_free = PG_private,

  56:  

  57:     /* SLUB */

  58:     PG_slub_frozen = PG_active,

  59: };

x) _count

引用计数,代表有多少处引用到该物理内存页对象。

访问_count时,不要直接访问,调用 page_count()对象进行访问。

x) private, mapping

   1: struct address_space {

   2:     struct inode        *host;        /* owner: inode, block_device */

   3:     struct radix_tree_root    page_tree;    /* radix tree of all pages */

   4:     spinlock_t        tree_lock;    /* and lock protecting it */

   5:     unsigned int        i_mmap_writable;/* count VM_SHARED mappings */

   6:     struct prio_tree_root    i_mmap;        /* tree of private and shared mappings */

   7:     struct list_head    i_mmap_nonlinear;/*list VM_NONLINEAR mappings */

   8:     struct mutex        i_mmap_mutex;    /* protect tree, count, list */

   9:     /* Protected by tree_lock together with the radix tree */

  10:     unsigned long        nrpages;    /* number of total pages */

  11:     pgoff_t            writeback_index;/* writeback starts here */

  12:     const struct address_space_operations *a_ops;    /* methods */

  13:     unsigned long        flags;        /* error bits/gfp mask */

  14:     struct backing_dev_info *backing_dev_info; /* device readahead, etc */

  15:     spinlock_t        private_lock;    /* for use by the address_space */

  16:     struct list_head    private_list;    /* ditto */

  17:     struct address_space    *assoc_mapping;    /* ditto */

  18: } __attribute__((aligned(sizeof(long))));

x) virtual

虚拟地址,如果是高端内存(HighMem),那么该物理页可能不是长久地映射到内核的内存空间中,所以该字段为NULL。

struct page

这个结构只是用来描述物理内存页,而与该页中存储的内容无关。

物理内存页的可能属主(Owner)有:

  • user-space processes, 用户态的进程
  • dynamically allocated kernel data, 内核态中动态分配的数据
  • static kernel code, 内核静态代码
  • the page cache,页缓存

可能程序员对为每个物理内存页都分配一个struct page而感到吃惊,“那得分配多少内存啊,多浪费啊!”。

实际上以4GB内存为例,大概需要40MB的内存来存储所有struct page的对象,相对于它能够管理的4GB物理内存,还是十分微不足道的。

2. Zones

“为什么不利用用户态的3GB的地址空间来映射内核的1GB地址空间映射不下的物理内存?”

因为其实,内核在工作时,是不考虑存在着用户空间的。

内核要处理的任务远比支撑用户空间要复杂。

为什么要使用不同的Zone?

有些硬件设备的DMA能访问的内存空间十分有即,比如x86的ISA总线,只能访问0~16M的物理内存,那么如果这段内存被随便地分配掉了,ISA设备就可能无法工作了。

ISA

ISA插槽是基于ISA总线(Industrial Standard Architecture,工业标准结构总线)的扩展插槽,其颜色一般为黑色,比PCI接口插槽要长些,位于主板的最下端。其工作频率为8MHz左右,为16位插槽,最大传输率16MB/sec,可插接显卡,声卡,网卡以及所谓的多功能接口卡等扩展插卡。其缺点是CPU资源占用太高,数据传输带宽太小,是已经被淘汰的插槽接口。(http://baike.baidu.com/view/13594.htm

HighMem

对于x86体系结构,以896MB物理内存为界,大于该范围的为高端内存(High Memory),而小于该范围的为低端内存(Low Memory)。

内核无法直接映射HighMem区域的物理内存,只能以暂时的方式映射其中一小部分使用,当需要使用其他的高端内存时,可以需要打破之前建立的暂时映射,而用于新的映射,就像是内存交换机制一样。

Linux Kernel Development有关内存管理的更多相关文章

  1. 【linux】arm mm内存管理

    欢迎转载,转载时请保留作者信息,谢谢. 邮箱:tangzhongp@163.com 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http:// ...

  2. [转载]linux段页式内存管理技术

    原始博客地址: http://blog.csdn.net/qq_26626709/article/details/52742470 一.概述 1.虚拟地址空间 内存是通过指针寻址的,因而CPU的字长决 ...

  3. <Linux内核源码>内存管理模型

    题外语:本人对linux内核的了解尚浅,如果有差池欢迎指正,也欢迎提问交流! 首先要理解一下每一个进程是如何维护自己独立的寻址空间的,我的电脑里呢是8G内存空间.了解过的朋友应该都知道这是虚拟内存技术 ...

  4. linux内核--用户态内存管理

    在上一篇博客“内核内存管理”中,描述的内核内存管理的相关算法和数据结构,在这里简单描述用户态内存管理的数据结构和算法. 一,相关结构体 与进程地址空间相关的全部信息都包含在一个叫做“内存描述符”的数据 ...

  5. 初探Linux内核中的内存管理

    Linux内核设计与实现之内存管理的读书笔记 初探Linux内核管理 内核本身不像用户空间那样奢侈的使用内存; 内核不支持简单快捷的内存分配机制, 用户空间支持? 这种简单快捷的内存分配机制是什么呢? ...

  6. Linux内核剖析 之 内存管理

    1. 内存管理区 为什么分成不同的内存管理区? ISA总线的DMA处理器有严格的限制:仅仅能对物理内存前16M寻址. 内核线性地址空间仅仅有1G,CPU不能直接訪问全部的物理内存. ZONE_DMA  ...

  7. linux 段页式内存管理

    http://blog.chinaunix.net/uid-24227137-id-3723898.html 页是信息的物理单位,分页是为了实现离散分配方式,以消减内存的外零头,提高内存的利用率从:或 ...

  8. [转]linux内核分析笔记----内存管理

    转自:http://blog.csdn.net/Baiduluckyboy/article/details/9667933 内存管理,不用多说,言简意赅.在内核里分配内存还真不是件容易的事情,根本上是 ...

  9. Linux Kernel 記憶體管理機制之美<转>

    转自--http://five.rdaili.com/sohu.com.php?u=Mq3EniVnae0axim7jkGhH0IhA9uho6CQso7R1aYomXWJ9UemfwUQYmKRc8 ...

随机推荐

  1. 修改 DbVisualizer 自动完成快捷键

    1.找到 DbVisualizer 安装目录 lib目录 下的 dbvis.jar 包. 2.使用 WinRaR 打开dbvis.jar包,编辑 dbvis-actions.xml 文件(解压或直接修 ...

  2. Java学习之面向对象特性-----封装

    面向对象特性一.封装(Encapsulation)封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式.好处: 将变化隔离 便于使用 提高复用性 提高安全性封装原则: 将不需要对外提供的内容都隐 ...

  3. 20140904 atoi字符串转化为整数源码

    1.atoi源码 #include<stdio.h> #include<assert.h> bool isdigit1(char c) { ') return true; el ...

  4. celery中配置redis密码时的ValueError: invalid literal for int() with base 10: 'xxxx'

    原配置: celery_broker = 'redis://:xxxx#xxxx@172.17.0.1:6379/0' # docker0 错误原因: 密码中不能有 # ? 等特殊字符 (无语O__O ...

  5. python 正则匹配

    正则表达式模式 模式字符串使用特殊的语法来表示一个正则表达式: 字母和数字表示他们自身.一个正则表达式模式中的字母和数字匹配同样的字符串. 多数字母和数字前加一个反斜杠时会拥有不同的含义. 标点符号只 ...

  6. LinkedBlockingQueue 学习

    LinkedBlockingQueue 链表队列,其元素构成为: static class Node<E> { E item; Node<E> next; Node(E x) ...

  7. 关于js中Ajax的同步、异步使用

    下面一个简单的例子,说明前后端交互中,Ajax同步和异步的使用 1.设置简单的一个div,包含触发事件 CompanyType() <div> <input type="h ...

  8. groupby 技术

    分组键可以有很多形式,且类型不必相同: 1.列表或数组,其长度与待分组的轴一样 2.表示DataFrame某个列名的值 3.字典或Series,给出待分组轴上的值与分组名之间的对应关系 4.函数,用于 ...

  9. Qt 【Qlistview + delegate 为item重写个关闭按钮】

    效果图是这样的. 实现的过程是listview + delegate 本身我想是用listwidget + delegate[网上查询到不可实现] 之前也试过在item中添加布局跟控件,但是在点击的时 ...

  10. Hadoop(三)YARN

    Yet Another Resources Negotiator 从Hadoop2.0版本开始引入YARN,主要功能: 集群资源管理系统 负责集群的统一管理和调度 与客户端交互,处理客户端请求 一.基 ...