内存那些事

简介:

内存那些事

linux中的free -m可以查看当前的内存使用情况

[yejianfeng@iZ23fsd ~]$ free -m
             total       used       free     shared    buffers     cached
Mem:          7869       7737        132          0        489       4419
-/+ buffers/cache:       2828       5040
Swap:            0          0          0

这里会让人奇怪的就是为什么除了used和free,还有个buffers,cached的使用。

buffer是系统把将要写入磁盘的数据先存放起来,然后一次性写入磁盘。cache则是将要从磁盘读取的数据先缓存起来,等待下次读取或者一次性读取。对于人来说,我们认为这一部分的缓存是已经使用了的,但是对于操作系统来说,这一部分的内存是“没有使用”的。因为这部分的内存随时可以释放。所以这部分意思是:

total: 总共有的内存
used: 已经使用的内存数(人的角度看的,既: 进程实际使用的内存+buffers+cached)
free: 空闲内存(人的角度看的)
shared: 进程共享内存
buffers: 操作系统预留的为进程IO读取使用的缓冲区
cached: 操作系统为最近打开的文件进行的缓存
-/+ buffer: 操作系统角度看的实际使用的内存数

虚拟内存和物理内存

我们在使用top命令看进程的时候,会看到下面的几个东西:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
2344 vagrant 20 0 98276 2020 1052 S 0.0 0.4 0:00.49 sshd
2345 vagrant 20 0 105m 1868 1488 S 0.0 0.4 0:00.08 bash
1136 nginx 20 0 45676 1740 440 S 0.0 0.4 0:00.00 nginx
1022 root 20 0 308m 1604 820 S 0.0 0.3 0:05.10 VBoxService

这里会看到几个属性:

VIRT RES SHR

这三个值都是表示这个进程的内存使用状况,其中的VIRT指的是进程使用的虚拟内存,RES指的是进程使用的物理内存,SHR指的是进程使用的共享内存。

关于虚拟内存和物理内存

打一个形象的比喻,一列车从北京到上海,有1500公里,我们应该要铺设1500公里的铁轨。但是,我们想了个取巧的办法,我们实际只需要三公里的铁轨,当列车快行驶完成铁轨的时候,我们把已经走过的铁轨铺设到列车前方,这样,列车就可以使用3公里的铁轨就进行行驶了。在这个例子中,虚拟内存就是代表1500公里,而物理内存就是代表3公里。我们一个进程在操作系统中实际使用的物理内存会远远小于分配的虚拟内存。比如一个php-fpm进程实际使用大概20-30M的物理内存,而你看他的虚拟内存,大概会有150M左右。

我们机器的内存是恒定的,那么这些大出来的虚拟内存是存放在哪里的呢?当然是硬盘。对于计算机来说,处理信息查找会先在L1缓存中找需要的数据,如果没有,在L2缓存中查找,如果还没有,在内存中查找,如果还没有,先去硬盘中的虚拟内存区域找,如果还没有,再去硬盘中找,如果都没有,就跳过这次处理(可能程序崩溃或者蓝屏)。

引入虚拟内存技术的好处是程序不需要再管物理内存中哪块空闲,哪块有用了。这些全部交给操作系统来管理,再程序面前,就像是有一块连续的,未使用的内存空间一样。当程序启动的时候,系统会为每个程序分配一定的内存空间。在32bit的机器上,这个内存空间的上限是4G(0x00000000 - 0xffffffff),而其中分为两个部分,用户态使用的内存,内核态使用的内存。其中3G(0x00000000 - 0xbfffffff)是用户态可以使用的内存,而1G(0xc0000000 - 0xffffffff)是内核态使用的内存。所以在许多windows的x86机器上,安装的内存条大小最多是4G的,因为安装再大的内存,可以使用的内存大小也是有限制的。

而对于64bit的机器,这个内存是没有4G的上限的,理论上可以支持2^64的大小的内存地址的。所以一般服务器上对内存的最大上限都不做限制,这点可以使用ulimit -a 得到验证:

[vagrant@localhost /]$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3528
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

对于虚拟内存和物理内存,这里其实最复杂的是他们的映射机制。这个机制是操作系统内核要实现的东东,这里就不继续看下去了。

共享内存

很多进程可能需要加载动态库,比如libc,而这些动态库就可以默认存放到共享内存中,而不用每个进程都进行加载了。还有进程也可以存放数据到共享内存中,这样他们的子进程就可以到共享内存中进行操作,比如php的shmop系列的命令就是操作共享内存的。

好了,这里有个奇怪的现象,明明top中在SHR中看到很多共享内存,为什么free -m中的shared为0呢?--实际上free命令中的shared已经被废弃了,没有进行计算了。具体参考man

目录
相关文章
|
4天前
|
Java
JVM之本地内存以及元空间,直接内存的详细解析
JVM之本地内存以及元空间,直接内存的详细解析
20 0
|
2天前
|
存储
内存
va的ava的内存需要划分成为5个部分: 1.栈(Stack)存放的都是方法中的局部变量。方法的运行一定要在栈当中运行。 2.堆(Heap)凡是new出来的东西,都是在堆当中 堆内存的东西都有一个地址值:16进制 堆内存的数据,都有默认值。规则: 整数 默认是0 浮点 默认0.0 字符 默认'\u0000' 布尔 默认false 引用类型 默认null 3.方法区(Method Area):存储class相关信息。包含方法的信息 4.本地方法栈(Native Method Stack):与操作系统相关需要划分成为5个部分: 1.栈(Stack)存放的都是方法中的局部变量。方法的运行一定要在栈当
10 0
|
1月前
|
存储 机器学习/深度学习 Java
什么是内存的动态分配
什么是内存的动态分配
8 0
|
3月前
|
存储 缓存 算法
内存分页机制
内存分页机制
23 0
|
4月前
|
缓存 Shell Perl
模拟占用磁盘内存CPU
模拟占用磁盘内存CPU
42 0
|
12月前
|
Linux API 芯片
什么是I/O内存?
I/O内存也称为Memory-Mapped I/O(MMIO), 它是指一种编址方式,不同cpu平台使用的编址方式不同,一种是“IO内存”方式,也叫统一编址方式,是指内存和外设的地址是在同一个地址空间上的,比如我们常见的ARM、MIPS等平台;还有另外一种叫独立编址方式,是指内存的地址空间和外设的地址空间是分开的,比如x86平台。
|
存储 缓存 Java
11-直接内存
不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域。
84 0
11-直接内存
|
存储 缓存 NoSQL
OHC堆外内存
巧用OHC堆外内存
492 0
OHC堆外内存
|
存储 缓存 Java
堆外内存及其在 RxCache 中的使用
堆外内存及其在 RxCache 中的使用
116 0
堆外内存及其在 RxCache 中的使用
|
存储 缓存 大数据
你不知道的内存知识
你不知道的内存知识