提交 9a19609a 编写于 作者: kingreatwill's avatar kingreatwill

内存

上级 2ddfcdc9
# 神奇的Cache 之旅
https://mp.weixin.qq.com/s?__biz=MzUzNzg4Nzc3MQ==&mid=2247483741&idx=1&sn=ee793706f2f35241de0de1264792db5b&chksm=fae15429cd96dd3f054a5416701d8926ec342d8e61e999f6a3ac2d44fe54737020d1e98d5e8b&mpshare=1&scene=1&srcid=&sharer_sharetime=1579405950129&sharer_shareid=16697c4af176d0bae6f144be947679f7&rd2werd=1#wechat_redirect
# Cache 缓存技术-1
https://mp.weixin.qq.com/s?__biz=MzUzNzg4Nzc3MQ==&mid=2247483702&idx=1&sn=acd3ef4ec6cd365177e25c127210afc7&chksm=fae15442cd96dd54926d6980a5e840b81ea631fde130a1a9c0e3fa2c86fd092329d533edc710&mpshare=1&scene=1&srcid=&sharer_sharetime=1579405978657&sharer_shareid=16697c4af176d0bae6f144be947679f7&rd2werd=1#wechat_redirect
# Cache 缓存技术-2
https://mp.weixin.qq.com/s?__biz=MzUzNzg4Nzc3MQ==&mid=2247483710&idx=1&sn=c40852dbf79759c5c12fa45981b7fbad&chksm=fae1544acd96dd5c10b02ffed57fbd283495d8933b5f5c5548a8fcb2a0140dabb2312643a368&mpshare=1&scene=1&srcid=&sharer_sharetime=1579405985264&sharer_shareid=16697c4af176d0bae6f144be947679f7&rd2werd=1#wechat_redirect
# Cache 缓存技术-3
https://mp.weixin.qq.com/s?__biz=MzUzNzg4Nzc3MQ==&mid=2247483723&idx=1&sn=7196767ae9548d6bb42eeb217690e6c6&chksm=fae1543fcd96dd294a2b520174168a9ecece10143aec8c2fd5cf41c0f649dd6040e79e0c4612&mpshare=1&scene=1&srcid=&sharer_sharetime=1579405991698&sharer_shareid=16697c4af176d0bae6f144be947679f7&rd2werd=1#wechat_redirect
# Cache 缓存技术-4
https://mp.weixin.qq.com/s?__biz=MzUzNzg4Nzc3MQ==&mid=2247483732&idx=1&sn=a89bdeb8cc12844a1316459262a26d68&chksm=fae15420cd96dd361d4be22cfcdfa206f74968f99fe809918242f9acdffe96a13a3ef7975cb9&mpshare=1&scene=1&srcid=&sharer_sharetime=1579405997012&sharer_shareid=16697c4af176d0bae6f144be947679f7&rd2werd=1#wechat_redirect
\ No newline at end of file
此差异已折叠。
......@@ -123,3 +123,44 @@ Linux 是如何用虚拟地址来映射物理地址的,我们用一张图来
- 提供进程间内存共享的方法(以虚拟内存的形式),也称作Shared Virtual Memory
在操作系统的控制下,硬件和系统软件为用户解决了上述问题,从而使应用程序的编程大大简化。
# 进程的虚拟地址空间
多任务操作系统中的每个进程都在其自己的内存沙箱中运行。此沙箱是虚拟地址空间,在32位模式下始终是4GB的内存地址块。这些虚拟地址通过页表映射到物理内存,页表由操作系统内核维护并由处理器查阅。
每个进程都有自己的一组页表,但有一个问题。启用虚拟地址后,它们将应用于计算机中运行的所有软件,包括内核本身。因此,必须为内核保留一部分虚拟地址空间
![](img/v-m-addr-1.png)
但这并不意味着内核使用了多少物理内存,这个是很重要的,初学者往往混淆虚拟地址和物理地址的概念 ,这里,每个进程只知道它拥有的可用映射它期望的物理内存地址空间的部分。内核空间在页表中标记为特权代码(ring 2或更低)专用,因此如果用户模式程序试图触摸它,则会触发页面错误。在Linux中,内核空间始终存在,并在所有进程中映射相同的物理内存。内核代码和数据始终是可寻址的,随时可以处理中断或系统调用。相反,只要发生进程切换,地址空间的用户模式部分的映射就会改变
![](img/v-m-addr-2.png)
蓝色区域表示映射到物理内存的虚拟地址,而白色区域未映射。在上面的示例中,Firefox已经使用了更多的虚拟地址空间。地址空间中的不同带对应于堆,堆栈等内存段。请记住,这些段只是一系列内存地址,与英特尔风格的段无关。下面这是Linux进程中的标准段布局:
![](img/v-m-addr-3.jpg)
蓝色区域表示映射到物理内存的虚拟地址,而白色区域未映射。在上面的示例中,由于当计算是快乐,安全和可爱的时,上面显示的段的起始虚拟地址几乎与机器中的每个进程完全相同。这使得远程利用安全漏洞变得容易。漏洞利用通常需要引用绝对内存位置:堆栈上的地址,库函数的地址等。远程攻击者必须盲目地选择此位置,依靠地址空间完全相同的事实。如果是这样的话,人们会被逮捕。因此地址空间随机化已经变得流行。Linux随机化堆栈, 内存映射段和堆通过向起始地址添加偏移量。不幸的是,32位地址空间非常紧张,几乎没有随机化的空间并妨碍其有效性。
进程地址空间中最顶部的段是堆栈,它在大多数编程语言中存储局部变量和函数参数。调用方法或函数会将新的堆栈帧压入堆栈。函数返回时会破坏堆栈帧。这种简单的设计,可能是因为数据遵循严格的LIFO顺序,这意味着不需要复杂的数据结构来跟踪堆栈内容 - 一个指向堆栈顶部的简单指针就可以了。因此,推动和弹出是非常快速和确定的。此外,堆栈区域的不断重用往往会在cpu缓存中保持活动堆栈内存,从而加快访问速度。进程中的每个线程都有自己的堆栈。
通过推送超出其能够容纳的数据,可以耗尽映射堆栈的区域。这会触发由expand_stack()在Linux中处理的页面错误,然后调用acct_stack_growth()来检查是否适合增长堆栈。如果堆栈大小低于RLIMIT_STACK(通常为8MB),那么通常堆栈会增长,程序会快速继续,不知道刚刚发生了什么。这是堆栈大小根据需求调整的常规机制。但是,如果已达到最大堆栈大小,则表示堆栈溢出并且程序收到分段错误。虽然映射的堆栈区域扩展以满足需求,但是当堆栈变小时它不会收缩, 它只会扩大。
动态堆栈增长是唯一一种访问未映射内存区域的情况,如上面的白色所示,可能是有效的。对未映射内存的任何其他访问都会触发导致分段错误的页面错误。参看我之前的文章Page Fault , 某些映射区域是只读的,因此对这些区域的写入尝试也会导致段错误。
在堆栈下面,我们有内存映射段。这里内核将文件内容直接映射到内存。任何应用程序都可以通过Windows中的Linux mmap()系统调用(实现)或CreateFileMapping()/ MapViewOfFile()来请求这种映射。内存映射是一种方便,高性能的文件I / O方式,因此用于加载动态库。还可以创建与任何文件不对应的匿名内存映射,而不是用于程序数据。在Linux中,如果通过malloc()请求大块内存,C库将创建这样的匿名映射,而不是使用堆内存。'大'意味着大于MMAP_THRESHOLD字节,默认为128 kB,可通过mallopt()调整。
说到堆,我们接下来就是地址空间。与堆栈不同,堆提供运行时内存分配(如堆栈),用于必须比执行分配的函数寿命更长的数据。大多数语言为程序提供堆管理。因此,满足内存请求是语言运行时和内核之间的联合事务。在C中,堆分配的接口是malloc(), 而在像C++这样的垃圾收集语言中,接口是new关键字。
如果堆中有足够的空间来满足内存请求,则语言运行时可以在没有内核参与的情况下处理它。否则,通过brk()系统调用(实现)扩大堆,以便为请求的块腾出空间。堆管理很复杂,需要复杂的算法,以便在我们程序的混乱分配模式面前争取速度和有效的内存使用。服务堆请求所需的时间可能会有很大差异。实时系统具有专用分配器来处理这个问题。堆也变得支离破碎,
![](img/v-m-addr-4.png)
最后,我们得到了最低的内存段:BSS,数据和程序文本。BSS和数据都存储C中静态(全局)变量的内容。区别在于BSS存储未初始化的静态变量的内容,其值不是由程序员在源代码中设置的。BSS内存区域是匿名的:它不映射任何文件。如果你说静态int cntActiveUsers,cntActiveUsers的内容就存在于BSS中。
另一方面,数据段保存源代码中初始化的静态变量的内容。此内存区域不是匿名的。它映射程序的二进制image的一部分,其中包含源代码中给出的初始静态值。因此,如果你说static int cntWorkerBees = 10,则cntWorkerBees的内容存在于数据段中并从10开始。即使数据段映射文件,它也是私有内存映射,这意味着内存更新不会反映出来在底层文件中。必须如此,否则对全局变量的赋值将改变您的磁盘二进制映像。不可思议!
下图中的数据示例比较棘手,因为它使用指针。在这种情况下,指针gonzo的内容 - 一个4字节的内存地址 - 存在于数据段中。但是,它指向的实际字符串不会。该字符串存在于文本段中,该段是只读的,除了像字符串文字这样的花絮之外,还存储了所有代码。文本段还将二进制文件映射到内存中,但写入此区域会使程序出现分段错误。这有助于防止指针错误,尽管不如首先避免C有效。这是一个显示这些段和示例变量的图表:
![](img/v-m-addr-5.png)
这就是虚拟地址空间布局
\ No newline at end of file
## cerebro
推荐使用cerebro,而且cerebro的使用特别简单,页面UI还很漂亮。cerebro是一个开源(MIT License)的Elasticsearch Web管理工具,使用Scala、Play Framework、AngularJS和Bootstrap构建。cerebro需要Java 1.8+ 运行环境。
1.下载并安装cerebro
可以到github下载最新版的cerebro v0.8.4,解压文件,运行bin/cerebro即可。
下面以windows 平台进行演示,Linux平台操作指令差不多。
2.启动cerebro
运行bin/cerebro即可,cerebro 的默认监听ip为0.0.0.0,默认端口为9000。
https://github.com/lmenezes/cerebro
## es-head
https://github.com/mobz/elasticsearch-head
## dejavu
https://github.com/appbaseio/dejavu/
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册