匿名文件映射问题 (概念不清晰)

光速跑者21 2015-11-17 10:10:17
看到《深入理解计算机系统》书中说,一个区域也可以映射到一个匿名文件,匿名文件是由内核创建的,包含的全是二进制零。当CPU第一次引用这样一个区域内的虚拟页面时,内核就在物理存储器中找到一个合适的牺牲页面,如果该页面被修改过,就将这个页面换出来,用二进制0覆盖牺牲页面,并更新页表,将这个页面标记为是驻留在存储器中的。因为这个原因,映射到匿名文件的区域中的页面,有时也叫做请求二进制0的页。
请问:1.什么叫CPU第一次引用这样一个区域内的虚拟页面,比如那个区域?
2.驻留在存储器中是标记为已分配未缓存吗?
3.映射到匿名文件区域页面什么意思?可以举个例子吗?
4.我们常说的swap区域是匿名文件吧,由内核创建的吗?为什么swap区域的大小限制着当前运行着的进程能够分配的虚拟页面总数?
...全文
1518 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
coreyspomu 2016-03-03
  • 打赏
  • 举报
回复
感谢大神Buddy.Zhang 的解答!刚好也是看这个书,遇到此处没看明白!
Buddy.Zhang 2016-03-03
  • 打赏
  • 举报
回复
引用 8 楼 linzihao0629 的回复:
恩,好的。那您了解meminfo日志中的AnonPages表示什么吗?我查了很多资料也没说清楚,它的增加是因为内存碎片化么?
匿名映射是通过优先查找树进行管理的,您要研究它的碎片问题,就从优先查找树作为切入点吧.
linzihao0629 2016-03-03
  • 打赏
  • 举报
回复
多谢Buddy.Zhang! 我会您给的程序测一下到底是哪一块代码造成匿名映射页激增的。
Buddy.Zhang 2016-03-03
  • 打赏
  • 举报
回复
引用 8 楼 linzihao0629 的回复:
恩,好的。那您了解meminfo日志中的AnonPages表示什么吗?我查了很多资料也没说清楚,它的增加是因为内存碎片化么?
通过函数 zone_page_state(z, NR_ANON_PAGES) 获得,您可以编写验证代码,如下 #include <linux/kernel.h> #include <linux/mmzone.h> void Test(void) { struct pglist_data *pgdat; struct zonelist *zonelist; struct zoneref *zrf; struct zone *zone; pgdat = NODE_DATA(0); zonelist = pgdat->node_zonelists; for_each_zone_zonelist(zone,zrf,zonelist,1) printk( KERN_INFO "The number of anonymous page is %p\n",zone_page_state(zone, NR_ANON_PAGES); } 通过上面的测试代码就可以查看内核中节点0 的 ZONE_NORMAL 和 ZONE_HIGHMEM 的匿名映射页的数量.
linzihao0629 2016-03-03
  • 打赏
  • 举报
回复
恩,好的。那您了解meminfo日志中的AnonPages表示什么吗?我查了很多资料也没说清楚,它的增加是因为内存碎片化么?
Buddy.Zhang 2016-03-03
  • 打赏
  • 举报
回复
引用 6 楼 linzihao0629 的回复:
程序是用C和C++语言写的,内存分配函数有malloc、calloc以及new等多种方式。
malloc ,calloc分配的内存就是使用匿名映射,建议您检查您的程序中 free() 是否干净
linzihao0629 2016-03-03
  • 打赏
  • 举报
回复
程序是用C和C++语言写的,内存分配函数有malloc、calloc以及new等多种方式。
Buddy.Zhang 2016-03-03
  • 打赏
  • 举报
回复
引用 4 楼 linzihao0629 的回复:
非常感谢Buddy.Zhang,解答得非常清晰明白。在这里想再请教一个问题,也是关于内存使用的,自己编写的一个简单服务器程序,在运行时查看/proc/meminfo日志,发现“MemFree+Buffers+Cached”的和在逐渐减少,而AnonPages这一项则在不断增加,这是为什么?是程序存在内存泄漏吗?
请问您的服务器程序内存分配函数使用的是哪一个?
linzihao0629 2016-03-03
  • 打赏
  • 举报
回复
非常感谢Buddy.Zhang,解答得非常清晰明白。在这里想再请教一个问题,也是关于内存使用的,自己编写的一个简单服务器程序,在运行时查看/proc/meminfo日志,发现“MemFree+Buffers+Cached”的和在逐渐减少,而AnonPages这一项则在不断增加,这是为什么?是程序存在内存泄漏吗?
nswcfd 2016-03-03
  • 打赏
  • 举报
回复
请教@Buddy.Zhang,为什么说anno page的碎片化问题跟priority tree有关系呢? (按照Documentation/prio_tree.txt的图示,这树应该是个区间树吧?)
光速跑者21 2015-11-27
  • 打赏
  • 举报
回复
谢谢回答,非常感谢,表示这块懂了。
Buddy.Zhang 2015-11-20
  • 打赏
  • 举报
回复
HI: 你好!很高兴能为你解决问题,我的回答只能作为参考,如有不对之处请立即指出,我会尽快答复你. 对应你的问题,我的解答如下: 对于这个问题,我先给你做一个简要的介绍. 在内核里,用户空间的进程要访问内存或磁盘里的数据要通过映射的方式将内存的物理地址和用户空间的虚拟地址联系起来. 用户通过访问这样的虚拟地址就可以访问到实际的物理地址,也就是实际的物理内存. 映射在实现虚拟地址到物理地址中扮演重要角色. 内核中映射分为文件映射和匿名映射. 文件映射就是磁盘中的数据通过文件系统映射到内存再通过文件映射映射到虚拟空间.这样,用户就可以在用户空间通过 open ,read, write 等函数区操作文件内容. 匿名映射就是用户空间需要分配一定的物理内存来存储数据,这部分内存不属于任何文件,内核就使用匿名映射将内存中的 某段物理地址与用户空间一一映射,这样用户就可用直接操作虚拟地址来范围这段物理内存. 至于实际的代码,文件映射的操作就是: open,read,write,close,mmap... 操作的虚拟地址都属于文件映射. malloc 分配的虚拟地址属于匿名映射. 好了,有了上面的简单介绍之后我就回答楼主的问题: 1.什么叫CPU第一次引用这样一个区域内的虚拟页面,比如那个区域? CPU 第一次访问匿名映射的空间,所谓的访问就是读或者写这部分区域. 根据 glibc 也就是用户空间对 malloc 分配的内存,如果不进行实际的访问,内核只分配虚拟地址,而不将虚拟地址通过匿名映射 与物理地址一一对应.只有 CPU 实际访问了这些区域,才真正发生匿名映射,也才发生缺页处理. CPU 第一次引用匿名区域时,由于匿名虚拟区还没有和实际的物理区域映射,内核就会发生一个缺页错误.于是内核就会 通过一些策略,从 swap 区获得一块物理内存页与之映射.这样虚拟地址就和物理地址挂钩,也就会生成相应的页表, 页表相关信息会被存储到 TLB 或 CACHE 中以假设虚拟地址到物理地址的转换. 2.驻留在存储器中是标记为已分配未缓存吗? 内核为了管理内存,会将物理内存分成 4K 大小的数据块进行管理,如果这块物理页已经分配出去了,这样的统计计数就会加 1, 其状态就会变成使用中,其也会被加入到正在使用物理页链表中.由于该页已经通过匿名映射分配出去了. 3.映射到匿名文件区域页面什么意思?可以举个例子吗? 对于页面这个概念,虚拟空间,内核有 0 ~ 4G 的虚拟地址,这些虚拟地址被分作大小 4K 的区域.这些区域要做页面. 对于实际物理内存,其也被分成大小为 4K 的区域,这些区域叫做物理页帧,用结构体 struct page 进行管理. 问题中所说的匿名文件页面指的就是物理内存的物理页帧,代码中表示为 struct page. 4.我们常说的swap区域是匿名文件吧,由内核创建的吗? 为什么swap区域的大小限制着当前运行着的进程能够分配的虚拟页面总数? swap 区叫做交换分区,是 Linux 采取的一种内存策略,通过把磁盘的内存当做物理内存来用.这样做的目的就是增大了 物理内存的大小,其明显的缺点就是速度没有物理内存快. swap 区域一般分作两部分,一部分位于物理内存,叫做 swapcache 区域,另外一部分位于磁盘上. 这里涉及的到换页,简单来说就是把不经常使用的匿名页帧置换到磁盘上.注意,内存存在两种映射: 匿名映射和文件映射,文件映射还和虚拟文件系统有关,它有自己的文件缓存和缓冲,文件映射的物理页帧是不会来自 swap区域 所以 swap 区域就是匿名映射的物理页帧.这个区域由内核创建并管理.

4,441

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧