上次介绍了物理内存管理中三位主要人物中的node 和zone。这两位是当官的,一个是县长,一个是里长,不敢不先介绍啊。接下来出场的就是我们的老百姓了 --- page frame。

Page frame是物理内存的基本组成单位,在Kernel中由结构体 struct page 来描述。

struct page {unsigned long flags;atomic_t _count;union {atomic_t _mapcount;unsigned int inuse;};union {struct {unsigned long private;struct address_space *mapping; };struct kmem_cache *slab;    /* SLUB: Pointer to slab */struct page *first_page;    /* Compound tail pages */};union {pgoff_t index;      /* Our offset within mapping. */void *freelist;     /* SLUB: freelist req. slab lock */};struct list_head lru;
};

这个结构体是不是长得很有特色?它里面的'union'特别多。

在中国,有好多大家不喜欢的制度,归根到底就一个原因 --- 人多。所以才有了户口制度来限制城市人口,所以才会采用高考制度来筛选人才。。。

在内存管理中,我们也面临着相同的问题 --- 内存页太多。假设我们有1G内存,采用4K的分页,则会有262144 (26万)个内存页,相应的就需要26万个struct page结构体。如果该结构体的大小增加一点点,放大26万倍,增加的内存消耗就很可观了。

为此,Kernel是绞尽了脑汁来减少该结构体的大小。毕竟全国百姓那么多,每个人多分配点田地,那整体的田地消耗太大。不像县长或里长这些当官的,数量有限,每个人多贪污点也影响不大。

Kernel采取的措施就是尽可能地重用同一个成员变量。房子大小有限,只能是白天当书房,晚上当卧室。

这就是为啥这个结构体中大量的使用了union。

  • flags: 用来描述page frame的属性或状态。

  • _count:这个没啥好说的,使用计数器。

  • _mapcount:也是个计数器,不过这里只是统计页表中有多少页表项指向该page frame。

  • inuse, slab, freelist:由slub使用,暂且略去不讲。

  • private:这个。。不同的使用场景下表示的含义也不同。为了节省空间而重用成员变量的另一种形式。是攻还是受,得看遇到了谁。

  • mapping:这个也是个多重人格,攻受兼备的主。一般会和 index 配合,表示在page cache中该page frame属于哪个address space。以后会详细讲到。

  • first_page: 在compound page中指向带头大哥。

  • lru: 还记不记得在结构体zone中有两个链表:active_list, inactive_list。嗯,lru就是干这个用的。

百闻不如一见。我们拿一个具体的例子,看看这三位人物的主要属性是怎么赋值的。

该实例中物理内存被分为两个node。

struct pglist_data {node_zones = ffff810000008101,node_zonelists = ffff81000000ad01,nr_zones = 3,node_mem_map = 0xffff8117df000000,node_start_pfn = 0,node_present_pages = 25162223,node_spanned_pages = 25427968,node_id = 0,kswapd_wait = ffff81000000d619,kswapd = 0xffff8117a27e3300,kswapd_max_order = 0
}
struct pglist_data {node_zones = ffff811840000000,node_zonelists = ffff811840002c00,nr_zones = 3,node_mem_map = 0xffff812fe0000000,node_start_pfn = 25427968,node_present_pages = 25165824,node_spanned_pages = 25165824,node_id = 1,kswapd_wait = ffff811840005518,kswapd = 0xffff8117a27e3300,kswapd_max_order = 0
}

我们以第一个Node为例,它被分成了三个zones:DMA, DMA32 and Normal。

  node_zones = {{pages_min = 0,pages_low = 0,pages_high = 0,lowmem_reserve = {0, 2978, 96722, 96722},node = 0,free_area =active_list = {next = 0xffff810000008a91,prev = 0xffff810000008a91},inactive_list = {next = 0xffff810000008aa1,prev = 0xffff810000008aa1},nr_scan_active = 0,nr_scan_inactive = 0,pages_scanned = 0,prev_priority = 12,wait_table = 0xffff810000001000,wait_table_hash_nr_entries = 16,wait_table_bits = 4,zone_pgdat = 0xffff810000008101,zone_start_pfn = 0,spanned_pages = 4096,present_pages = 1233,name = 0xffffffff8058c55c "DMA"}, {pages_min = 216,pages_low = 270,pages_high = 324,lowmem_reserve = {0, 0, 93744, 93744},node = 0,free_area = active_list = {next = 0xffff810000009591,prev = 0xffff810000009591},inactive_list = {next = 0xffff8100000095a1,prev = 0xffff8100000095a1},nr_scan_active = 0,nr_scan_inactive = 0,pages_scanned = 0,prev_priority = 12,wait_table = 0xffff810001000000,wait_table_hash_nr_entries = 4096,wait_table_bits = 12,zone_pgdat = 0xffff810000008101,zone_start_pfn = 4096,spanned_pages = 1044480,present_pages = 762517,name = 0xffffffff8056824d "DMA32"}, {pages_min = 6819,pages_low = 8523,pages_high = 10228,lowmem_reserve = {0, 0, 0, 0},node = 0,free_area =active_list = {next = 0xffff81180da37e68,prev = 0xffff81183d80b528},inactive_list = {next = 0xffff81180f4e6be8,prev = 0xffff81183d823b68},nr_scan_active = 0,nr_scan_inactive = 0,pages_scanned = 0,prev_priority = 12,wait_table = 0xffff810001020000,wait_table_hash_nr_entries = 4096,wait_table_bits = 12,zone_pgdat = 0xffff810000008101,zone_start_pfn = 1048576,spanned_pages = 24379392,present_pages = 23998464,name = 0xffffffff80568253 "Normal"
}

至此物理内存管理中三位主要人物就介绍完了。他们之间都有些什么恩怨情仇血雨腥风的故事呢?敬请期待!

转载于:https://blog.51cto.com/richardguo/1663808

Kernel那些事儿之内存管理(2) --- 百闻不如一见相关推荐

  1. Kernel那些事儿之内存管理(8) --- Slab(中)

    上篇讲了Slab中的数据结构,这篇该讲Slab中的操作了. 既然是内存管理,那操作无非就两点:allocate 和 free. 1. 申请一个object 在Slab中,申请一个object是通过函数 ...

  2. Kernel那些事儿之内存管理(7) --- Slab(上)

    前面讲的buddy system算法,分配内存的最小单位是一个页面(例如 4K).这对于大的内存申请比较适用.可是实际生活中,Kernel经常需要分配小的内存空间,比如几十个字节,这个时候怎么办呢? ...

  3. Kernel那些事儿之内存管理(5) --- 衣带渐宽终不悔(上)

    Kernel中负责分配一个连续内存页块的子系统一般被称为zoned page frame allocator.前面讲了函数 buffered_rmqueue() 是如何从指定zone的buddy sy ...

  4. linux chown 将root改变所有者为admin,Linux用户管理 权限管理 内存管理 网络管理命令 (第四天)...

    默认添加的用户会自动加入和用户名一样的组中 su 切换用户 查看当前登陆的用户: whoami id` 查看当前用户属于哪个组:groups groupadd 组名 添加组 groupdel 组名 删 ...

  5. 操作系统内存管理,你能回答这8个问题吗?

    # 干了这碗鸡汤 当我们是少数人时,我们要有勇气做自己:当我们是多数人时,我们要有胸襟容得下他人. -- 拉尔夫·W·索克曼 大家早上好,今天为大家总结整理了关于操作系统内存管理的知识点,更文不易,请 ...

  6. linux kernel 内存管理 感想总结(未完待续)

    理解内存管理需要知道的概念 什么是 MMU , MMU的作用? 什么是页帧,页,页表,区,他们之间的关系又是怎样的 ? 什么是页的高速缓存 地址线, 寻址, cpu 和 各级高速缓存的关系, cpu ...

  7. [内存管理] linux kernel内存映射实例分析

    作者:JHJ(jianghuijun211@gmail.com ) 日期:2012/08/24 欢迎转载,请注明出处 引子 现在android智能手机市场异常火热,硬件升级非常迅猛,arm corte ...

  8. Linux内存管理:MMU那些事儿

    <ARM SMMU原理与IOMMU技术("VT-d" DMA.I/O虚拟化.内存虚拟化)> <Linux内存管理:分页机制> <Linux内存管理:内 ...

  9. 内存管理器(十)kernel内存管理----数据结构

    内存管理器(十) kernel内存管理----概况与数据结构 前言 正式开始学习内核的内存管理了,先学习下接口函数,每一个例字都必须写内核模块实验,然后深入到函数的内部研究源码,最后写写练习的小程序. ...

最新文章

  1. 手把手教你如何建立自己的Linux系统(二)
  2. 去除php_eol,php去除换行符的方法小结(PHP_EOL变量的使用)
  3. android+无触摸操作,如何在Android中模拟触摸事件?
  4. 使用dbcp连接池创建进行表的增删改查
  5. MAUI 移植 Xamarin.Forms 自定义渲染器
  6. 纸机器人的折法_好神奇!他们竟用一张纸折成了一个机器人
  7. 表格锁定表头不动_Excel教程:你有没有被表头难过?分享几招搞定(下)
  8. Ubuntu无法ping通外网可以ping通内网
  9. 屏蔽登录QQ后总是弹出的QQ网吧页面
  10. CF724G. Xor-matic Number of the Graph
  11. 巨详细的iphone新手教程
  12. 非功能测试之本地化和国际化测试
  13. linux安装时找不到硬盘分区,在安装linux时出现找不到硬盘如何解决
  14. linux(五)——TX1的cpu/gpu锁频(设置最大频率)
  15. RTF文件格式编码说明
  16. 华为android手机root,华为手机怎么root
  17. 第十六届—振兴杯计算机网络管理员决赛模拟题
  18. Kafka集群的搭建与批量启停
  19. dedecms 栏目绑定二级域名
  20. 鸢尾花(iris)数据集保存到本地以及sklearn其他数据集下载保存

热门文章

  1. 再次学习javascript中的參数传递
  2. CSRFGuard工具介绍
  3. 微信小程序与Java后台的通信
  4. FPFH+ICP点云配准
  5. EC+VO+SCOPE for ES3
  6. 订单不断,我是这样做的
  7. 微软获得O/R映射技术专利 业界担忧阻碍技术进展
  8. 表单提交enctype参数详解之:application/x-www-form-urlencode和multipart/form-data
  9. maskView与CAGradientLayer详解
  10. spring boot 加载application配置文件