Ø查看内存的物理地址范围
[root@node01 ~]# cat /proc/iomem
00000000-00000fff : reserved
00001000-0009ebff : System RAM
0009ec00-0009ffff : reserved
000a0000-000bffff : PCI Bus 0000:00
...
000dc000-000fffff : reserved
000f0000-000fffff : System ROM
00100000-7fedffff : System RAM
2b000000-350fffff : Crash kernel
72600000-72d9425e : Kernel code
72d9425f-7336817f : Kernel data
73562000-7386efff : Kernel bss
7fee0000-7fefefff : ACPI Tables
7feff000-7fefffff : ACPI Non-volatile Storage
7ff00000-7fffffff : System RAM
Ø查看zone的信息
[root@node01 ~]# cat /proc/zoneinfo
Node 0, zone DMA
pages free 1979
min 96
low 120
high 144
scanned 0
spanned 4095
present 3997
managed 3976
nr_free_pages 1979
nr_alloc_batch 20
nr_inactive_anon 654
…
Node 0, zone DMA32
Ø查看伙伴系统的信息
root@node01 ~]# cat /proc/buddyinfo
Node 0, zone DMA 33 15 14 5 8 5 0 2 1 2 0
Node 0, zone DMA32 3519 5656 2514 1031 248 41 3 0 0 0 0
[root@node01 ~]# cat /proc/pagetypeinfo
Free pages count per migrate type at order 0 1 2 3 4 5 6 7 8 9 10
Node 0, zone DMA, type Unmovable 6 6 7 5 4 1 0 1 0 0 0
Node 0, zone DMA, type Reclaimable 1 0 1 0 2 3 0 0 1 1 0
Node 0, zone DMA, type Movable 23 9 6 0 2 1 0 1 0 1 0
Node 0, zone DMA, type Reserve 0 0 0 0 0 0 0 0 0 0 0
Node 0, zone DMA, type CMA 0 0 0 0 0 0 0 0 0 0 0
Node 0, zone DMA, type Isolate 0 0 0 0 0 0 0 0 0 0 0
Ø查看slab的信息 pagesperslab * num_slabs *4K ==占用内存大小
[root@node01 ~]# cat /proc/slabinfo
slabinfo - version: 2.1
# name <active_objs> <num_objs> <objsize> <objperslab> <pagesperslab> : tunables <limit> <batchcount> <sharedfactor> : slabdata <active_slabs> <num_slabs> <sharedavail>
xfs_dqtrx 0 0 528 62 8 : tunables 0 0 0 : slabdata 0 0 0
xfs_inode 14807 20434 960 34 8 : tunables 0 0 0 : slabdata 601 601 0
...
kmalloc-96 3948 3948 96 42 1 : tunables 0 0 0 : slabdata 94 94 0
kmalloc-64 16401 19840 64 64 1 : tunables 0 0 0 : slabdata 310 310 0
kmalloc-32 12482 15616 32 128 1 : tunables 0 0 0 : slabdata 122 122 0
kmalloc-16 32426 49664 16 256 1 : tunables 0 0 0 : slabdata 194 194 0
kmalloc-8 8704 8704 8 512 1 : tunables 0 0 0 : slabdata 17 17 0
[root@node01 ~]# cat /proc/vmallocinfo
0xffffb751c0000000-0xffffb751c0002000 8192 hpet_enable+0x2d/0x317 phys=fed00000 ioremap
0xffffb751c0002000-0xffffb751c0203000 2101248 alloc_large_system_hash+0x188/0x25c pages=512 vmalloc N0=512
0xffffb751c0203000-0xffffb751c0304000 1052672 alloc_large_system_hash+0x188/0x25c pages=256 vmalloc N0=256
0xffffb751c0304000-0xffffb751c030d000 36864 alloc_large_system_hash+0x188/0x25c pages=8 vmalloc N0=8
0xffffb751c030d000-0xffffb751c0316000 36864 alloc_large_system_hash+0x188/0x25c pages=8 vmalloc N0=8
0xffffb751c0316000-0xffffb751c0318000 8192 acpi_os_map_memory+0xfd/0x155 phys=7feff000 ioremap
0xffffb751c031c000-0xffffb751c031e000 8192 usb_hcd_pci_probe+0x143/0x560 phys=fd5bf000 ioremap
0xffffb751c0336000-0xffffb751c0357000 135168 raw_init+0x41/0x141 pages=32 vmalloc N0=32
0xffffb751c0357000-0xffffb751c035c000 20480 agp_add_bridge+0x2da/0x480 pages=4 vmalloc N0=4
0xffffb751c03a8000-0xffffb751c03aa000 8192 vmballoon_work+0x1f9/0x6ff [vmw_balloon] vmap
用户态内存映射
以32位X86系统为例,每个用户态进程的地址空间为3G,在需要时,操作系统为地址空间映射物理内存,供进程使用,一般的过程是:
1、进程通过malloc()函数申请内存,用户态的内存管理算法通过brk()/mmap()系统调用,会得到一段地址空间,经过内存管理算法对空间进行划分,返回一个虚拟地址;
2、进程访问虚拟地址,由于虚拟地址没有映射的物理内存,会产生缺页异常;
3、操作系统处理缺页异常,通过伙伴系统算法分配物理页,设置页表项,将物理地址映射到虚拟地址上,返回用户态进程继续运行;
4、用户态进程此时就可以访问虚拟地址了。
缺页异常的处理,对于用户态进程来说是透明的,它并不感知这一过程。并且,虚拟地址一旦映射,操作系统里会保存期页表项,下次访问不会再次产生缺页异常。
1、空闲内存很少,怎样确定谁占用了大量内存?
cat /proc/meminfo,先大致确定是哪些部分占用的内存多,然后再详细查询
MemTotal: 1863100 kB
MemFree: 1495220 kB
MemAvailable: 1522176 kB
Buffers: 2108 kB
Cached: 147860 kB // 1)内存文件系统及文件缓存占用的内存 echo 3 > /xx/xx/vm/drop_cache
SwapCached: 0 kB
…
AnonPages: 72496 kB // 2)AnonPages及Mapped是用户态占用的内存
Mapped: 36128 kB
Slab: 68760 kB // 3)slab分配器占用的内存,具体查询/proc/slabinfo
…
KernelStack: 4480 kB // 内核线程栈占用的内存
PageTables: 8332 kB // 页表项占用的内存
VmallocTotal: 34359738367 kB
VmallocUsed: 180368 kB // 4)vmalloc空间的使用情况,并不完全是内存,具体查询/proc/vmallocinfo
1、空闲内存剩余还有很多,为什么kmalloc失败?
1)注意kmalloc申请的内存大小;可能情况是系统剩余内存还很多,但是碎片化比较严重,已经没有这么大的连续内存了。
2)如果是32位的设备,要注意kmalloc是只能申请lowmem(DMA/NORMAL)的,有可能Free内存比较多,但是lowmem已经很少了
通过查看/proc/buddyinfo来确认上述两点
2、空闲内存剩余还有很多,为什么malloc失败?
1)空闲内存不够,malloc不会返回NULL;而是在访问内存时,触发OOM。
2)用户态malloc返回NULL,一般是进程的地址空间不够了,在32位的系统上地址空间小,容易出现这样的问题。通过/proc/<pid>/maps来查看地址空间的使用情况。