暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

linux基础——内存

爱可可的人生记录仪 2020-01-19
356
今天有同事系统内存不够了,想申请扩容,我free了一下,内存不还是绰绰有余吗?他回了一句,那个free不是只剩1G不到了嘛。嗯,确实如此,但是系统实际可用的内存,应该是下面的那个+buffers/cache,还有10G左右的空间。 当然如果是新版本的free命令的话,显示结果会更友好一点。同事没有去深究,虽然计算机的问题都经不起问为什么,不过,这次,我想往里走一点,看看内存到底是怎么工作的?

(旧版)

(新版)

内存映射

我们常说的内存指的是物理内存,但物理内存只有内核才可以访问,那么进程如何访问呢?Linux 内核会给每个进程都提供了一个独立的虚拟地址空间,这就是我们常说的虚拟内存。虚拟地址空间的内部又被分为内核空间和用户空间两部分,不同字长的处理器,空间范围也不同。进程也有用户态和内核态,用户态的只能访问用户空间,切换到内核态才可以访问内核空间内存。当然,并不是所有的虚拟空间都会分配物理内存,按需分配,这种分配的方式是通过内存映射来管理的。内核为每个进程都维护了一张页表,用来记录映射关系。当进程访问的虚拟地址在页表中查不到时,系统会产生一个缺页异常,进入内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。
内存映射的最小单位是页,通常为4KB,linux提供了多级页表和大页的机制来解决页表过大的问题。多级页表就是把内存分成区块来管理,将原来的映射关系改成区块索引和区块内的偏移。大页就是比普通页更大的内存块,常见的大小有 2MB 和 1GB。在页表的映射下,进程就可以通过虚拟地址来访问物理内存了。

虚拟内存空间分布

操作系统为了解决I/O底层的差异,创建了VFS(虚拟文件系统),为了解决I/O层与内存之间的差异,产生了虚拟内存。为了解决cpu与内存之间的差异,创建了进程。每个程序运行起来都会拥有一个自己的虚拟地址空间,32位cpu的操作系统,其地址线也为32位,所以虚拟地址空间为2^32 -1= 4G。虚拟内存最上方是内核空间,下方是用户空间,用户空间又分为多段。从高到低依次为:栈,文件映射段,堆,数据段,只读段。更详细的划分去网上搜吧。可以通过proc的maps查看具体分布。


内存分配与回收

malloc() 是 C 标准库提供的内存分配函数,对应到系统调用上,有两种实现方式,即 brk() 和 mmap()。
对小块内存(小于 128K),C 标准库使用 brk() 来分配,也就是通过移动堆顶的位置来分配内存。这些内存释放后并不会立刻归还系统,而是被缓存起来,这样就可以重复使用。可以减少缺页异常,提高内存访问率,但频繁的访问会造成内存碎片。
而大块内存(大于 128K),则直接使用内存映射 mmap() 来分配,也就是在文件映射段找一块空闲内存分配出去。用完会立刻归还系统,繁忙会造成大量的缺页异常,使内核的管理负担变大。
在内核空间,Linux 则通过 slab 分配器来管理比页还小的小内存对象。在应用程序用完内存后,还需要调用 free() 或 unmap() ,来释放这些不用的内存。
如果内存紧张,会通过一系列机制来回收内存,如LRU,swap,以及OOM。OOM有个om_adj ,范围是 [-17, 15],数值越大,表示进程越容易被 OOM 杀死,可以改写proc使一些重要程序不会被OOM杀死。



echo -16 > /proc/$(pidof mysqld)/oom_adj



查看内存使用

free
buff/cache 是缓存和缓冲区的大小;
available 是新进程可用内存的大小。available 不仅包含未使用内存,还包括了可回收的缓存,但并不是所有缓存都可以回收。
top
VIRT 是进程虚拟内存的大小,只要是进程申请过的内存,即便还没有真正分配物理内存,也会计算在内。
RES 是常驻内存的大小,也就是进程实际使用的物理内存大小,但不包括 Swap 和共享内存。
SHR 是共享内存的大小,比如与其他进程共同使用的共享内存、加载的动态链接库以及程序的代码段等。
%MEM 是进程使用物理内存占系统总内存的百分比。


题外话:MySQL啃不动了,先换换口味吧,快过年了,今天上班少了一大波人,办公室冷清的很。只要系统别挂,我应该也能摸几天鱼了,最近处在倦怠期,动力不是很大,嗯。。。打算写个年终总结,看心情吧。




参考资料:倪朋飞,Linux性能优化实战



部分内容来自网络,如有侵权请联系作者删除。





文章转载自爱可可的人生记录仪,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论