#linux 内存、磁盘、进程、网络分析

时间:2022-03-24 22:49:16

1 内存

[root@localhost ~]# free -m
total used free shared buffers cached
Mem: 15951 13825 2125 0 145 3017
-/+ buffers/cache: 10662 5289
Swap: 8191 0 8191

[root@localhost ~]# top
top - 16:26:48 up 778 days, 6:56, 2 users, load average: 0.00, 0.00, 0.00
Tasks: 121 total, 1 running, 120 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.1%us, 0.1%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
10380 root 20 0 15024 1328 1012 R 0.3 0.0 0:00.04 top
1 root 20 0 19228 1512 1224 S 0.0 0.0 0:11.94 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.20 kthreadd
3 root RT 0 0 0 0 S 0.0 0.0 0:01.76 migration/0
4 root 20 0 0 0 0 S 0.0 0.0 0:32.40 ksoftirqd/0
5 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0

[root@localhost ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 20G 4.8G 14G 26% /
tmpfs 7.8G 0 7.8G 0% /dev
/shm
/dev
/sda1 2.0G 87M 1.8G 5% /boot
/dev/sda5 69G 491M 65G 1% /export

内存去哪了?

Filesystem            Size  Used Avail Use% Mounted on
tmpfs 7.8G 0 7.8G 0% /dev/shm

1.1 /dev/shm

是一个设备文件,, 可以把/dev/shm看作是系统内存的入口, 可以把它看做是一块物理存储设备,

一个tmp filesystem, 你可以通过这个设备向内存中读写文件, 以加快某些I/O高的操作,比如对一个大型文件频繁的open, write, read,

可以通过mount命令列出当前的/dev/shm的挂载的文件系统,你可以直接对/dev/shm进行读写操作, 例如:

# touch /dev/shm/file1

既然是基于内存的文件系统,系统重启后/dev/shm下的文件就不存在了。
Linux默认(CentOS)/dev/shm分区的大小是系统物理内存的50%, 虽说使用/dev/shm对文件操作的效率会高很多,但是目前各发行软件中却很少有使用它的。可以通过ls /dev/shm查看下面是否有文件, 如果没有就说明当前系统并没有使用该设备.

什么是tmpfs和/dev/shm/?

tmpfs是Linux/Unix系统上的一种基于内存的文件系统。tmpfs可以使用您的内存或swap分区来存储文件。
tmpfs主要存储暂存的文件。它有如下2个优势 : 1. 动态文件系统的大小。2. tmpfs 的另一个主要的好处是它闪电般的速度。

典型的 tmpfs 文件系统会完全驻留在内存 RAM 中,读写几乎可以是瞬间的。同时它也有一个缺点 tmpfs 数据在重新启动之后不会保留

tmpfs是基于内存的文件系统,创建时不需要使用mkfs等初始化。如想改变/dev/shm tmpfs大小,修改/etc/fstab的

devpts /dev/pts devpts gid=5,mode=620 0 0

然后执行

mount -o remount /dev/shm

tmpfs(/dev/shm)的使用及应用场景

先在/dev/shm建一个tmp目前,并与/tmp绑定。

# mkdir /dev/shm/tmp
# chmod 1777 /dev/shm/tmp
# mount --bind /dev/shm/tmp /tmp
# ls -ld /tmp
卸载
# umount /dev/shm

1.2 Swap

现代操作系统都实现了“虚拟内存”这一技术,不但在功能上突破了物理内存的限制,使程序可以操纵大于实际物理内存的空间,更重要的是,“虚拟内存”是隔离每个进程的安全保护网,使每个进程都不受其它程序的干扰。

在使用Windows系统时,可以同时运行多个程序,当你切换到一个很长时间没有理会的程序时,会听到硬盘“哗哗”直响。这是因为这个程序的内存被那些频繁运行的程序给“偷走”了,放到了Swap区中。因此,一旦此程序被放置到前端,它就会从Swap区取回自己的数据,将其放进内存,然后接着运行。

并不是所有从物理内存中交换出来的数据都会被放到Swap中(如果这样的话,Swap就会不堪重负),有相当一部分数据被直接交换到文件系统。例如,有的程序会打开一些文件,对文件进行读写(其实每个程序都至少要打开一个文件,那就是运行程序本身),当需要将这些程序的内存空间交换出去时,就没有必要将文件部分的数据放到Swap空间中了,而可以直接将其放到文件里去。如果是读文件操作,那么内存数据被直接释放,不需要交换出来,因为下次需要时,可直接从文件系统恢复;如果是写文件,只需要将变化的数据保存到文件中,以便恢复。

swapoff -a  禁用swap
swapon -a 启用

3 buffer/cache

How do you empty the buffers and cache on a Linux system?

# free && sync && echo 3 > /proc/sys/vm/drop_caches && free
$ echo "echo 1 > /proc/sys/vm/drop_caches" | sudo sh
# yum install -y libmemcached 

#pidof nginx 仅查找进程的所有pid
# memstat -p 3535

top

VIRT:进程占用的虚拟内存
RES:进程占用的物理内存
SHR:进程使用的共享内存
S:进程的状态。S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值为负数
%CPU:进程占用CPU的使用率
%MEM:进程使用的物理内存和总内存的百分比
TIME+:该进程启动后占用的总的CPU时间,即占用CPU使用时间的累加值。
COMMAND:进程启动命令名称

常用的命令(大写):
  P:按%CPU使用率排行
  T:按TIME+排行
  M:按%MEM排行

pmap

可以根据进程查看进程相关信息占用的内存情况,(进程号可以通过ps查看)如下所示:
$ pmap -d 14596

ps

$ ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid'  其中rsz是是实际内存
$ ps -e -o 'pid,comm,args,pcpu,rsz,vsz,stime,user,uid' | grep oracle | sort -nrk5

其中rsz为实际内存,上例实现按内存排序,由大到小

linux下查看最消耗CPU、内存的进程

  
1.CPU占用最多的前5个进程:
ps auxw|head -1;ps auxw|sort -rn -k3|head -5
ps auxw|head -1是为了打印标题
2.内存消耗最多的前5个进程
ps auxw|head -1;ps auxw|sort -rn -k4|head -5
3.虚拟内存使用最多的前5个进程
ps auxw|head -1;ps auxw|sort -rn -k5|head -5

4.也可以试试
ps auxw –sort=rss
ps auxw –sort=%cpu

5.看看几个参数含义

%MEM 进程的内存占用率
VSZ 进程所使用的虚存的大小
RSS 进程使用的驻留集大小或者是实际内存的大小(RSS is the “resident set size” meaning physical memory used)
TTY 与进程关联的终端(tty)

STAT 检查的状态:进程状态使用字符表示的,如R(running正在运行或准备运行)、S(sleeping睡眠)、I(idle空闲)、Z (僵死)、D(不可中断的睡眠,通常是I/O)、P(等待交换页)、W(换出,表示当前页面不在内存)、N(低优先级任务)T(terminate终止)、W has no resident pages

D 不可中断 Uninterruptible sleep (usually IO)
R 正在运行,或在队列中的进程
S 处于休眠状态
T 停止或被追踪
Z 僵尸进程
W 进入内存交换(从内核2.6开始无效)
X 死掉的进程

<    高优先级 
N 低优先级
L 有些页被锁进内存
s 包含子进程
+ 位于后台的进程组;
l 多线程,克隆线程 multi-threaded (using CLONE_THREAD, like NPTL pthreads do)

free(1024进制)

$ free -g
total used free shared buffers cached
Mem: 15 15 0 0 2 0
-/+ buffers/cache: 12 2
Swap: 17 0 17

这台服务器有16G内存,但是结果显示除了2G左右的文件Buffer缓存外,其余十几G都被确确实实的用光了。(free按1024进制计算,总内存可能比实际偏小)
#linux 内存、磁盘、进程、网络分析

top看了下,没有特别吃内存的程序。用ps大概统计下所有程序占用的总内存:

$ ps aux | awk '{mem += $6} END {print mem/1024/1024}'
0.595089

结果显示所有进程占用的内存还不到1G,实际上,因为free, ps的统计方式的差别和Copy-on-write和Shared libraries等内存优化机制的存在,这两者的统计结果通常是不一样的。但是一般情况下绝对不会相差十几个G,肯定是有什么隐藏的问题,Google了许久后发现,free没有专门统计另一项缓存: Slab

Slab简介和进一步调查

Slab Allocation是Linux 2.2之后引入的一个内存管理机制,专门用于缓存内核的数据对象,可以理解为一个内核专用的对象池,可以提高系统性能并减少内存碎片。(Linux 2.6.23之后,SLUB成为了默认的allocator。)
查看Slab缓存 $ cat /proc/meminfo
其中,Slab相关的数据为

Slab:  154212 kB
SReclaimable: 87980 kB
SUnreclaim: 66232 kB

SReclaimable(Linux 2.6.19+)都是clean的缓存,随时可以释放。回到之前的内存问题,我查了下那台服务器上Slab占用的内存:

$ cat /proc/meminfo | grep Slab
Slab: 12777668 kB

12G的Slab缓存,有意思的是free把Slab缓存统计到了used memory中,这就是之前那个问题的症结所在了。
另外,还可以查看/proc/slabinfo(或使用slabtop命令)来查看Slab缓存的具体使用情况。结果发现,ext3_inode_cache和dentry_cache占用了绝大部分内存。

考虑到这台服务器会频繁地用rsync同步大量的文件,这个结果也并不意外。

解决问题

先说明一下,如果问题仅仅是Slab占用了太多的内存(SReclaimable),那么通常不需要太操心,因为这根本不是个问题(如果是SUnreclaim太多且不断增长,那么很有可能是内核有bug)。但是,如果是因为Slab占用内存太多而引起了其他的问题,建议继续阅读。
清除Slab可回收缓存
通过/proc/sys/vm/drop_caches这个配置项,可以手动清除指定的可回收缓存(SReclaimable)[2]

echo 2 > /proc/sys/vm/drop_caches

上面的命令会主动释放Slab中clean的缓存(包括inode和dentry的缓存),然后再free -g一下,未使用的内存陡增了十几个G。。
需要注意的是,手动清除缓存可能会在一段时间内降低系统性能。原则上不推荐这么做,因为如果有需要,系统会自动释放出内存供其他程序使用。

另外,手动清除Slab缓存是一个治标不治本的办法。因为问题不在Slab,而在于我们那个会引起Slab缓存飙涨的进程(我这里应该是rsync)。实际操作的时候发现,清除缓存一段时间后,Slab缓存很快又会“反弹”回去。如果需要治本,要么搞定问题进程,要么修改系统配置。

调整系统vm配置
风险预警: 调整以下系统配置可能会对系统性能造成负面影响,请仔细测试并谨慎操作。
/etc/sysctl.conf里有几个对内存管理影响比较大的配置,

  • vm.vfs_cache_pressure
    系统在进行内存回收时,会先回收page cache, inode cache, dentry cache和swap cache。vfs_cache_pressure越大,每次回收时,inode cache和dentry cache所占比例越大

    vfs_cache_pressure默认是100,值越大inode cache和dentry cache的回收速度会越快,越小则回收越慢,为0的时候完全不回收(OOM!)。

  • vm.min_free_kbytes
    系统的”保留内存”的大小,”保留内存”用于低内存状态下的”atomic memory allocation requests”(eg. kmalloc + GFP_ATOMIC),该参数也被用于计算开始内存回收的阀值,默认在开机的时候根据当前的内存计算所得,越大则表示系统会越早开始内存回收。

    min_free_kbytes过大可能会导致OOM,太小可能会导致系统出现死锁等问题。

  • vm.swappiness
    控制系统将内存swap out到交换空间的积极性,取值范围是[0, 100]。swappiness越大,系统的交换积极性越高,默认是60,如果为0则不会进行交换。

参考:
Linux System IO Monitoring
Paging
Understanding the Linux Virtual Memory Manager
Linux终端:用smem查看内存占用情况
http://os.51cto.com/art/201312/422124.htm
正确理解Linux内存占用过高的问题
http://blog.licess.com/linux-memory/
Ubuntu 使用top/free查看内存占用大的原因
https://fukun.org/archives/02201800.html

linux下查询进程占用的内存方法总结
https://segmentfault.com/a/1190000004147558

lsof在Linux中的10个例子<译>
http://kumu-linux.github.io/blog/2013/04/08/lsof/

Linux下内存使用分析思路
http://www.361way.com/memory-analysis/5018.html

Linux Used内存到底哪里去了?
http://blog.yufeng.info/archives/2456

查看内存引出的那些事儿
http://www.centoscn.com/CentOS/help/2015/0320/4937.html

Linux查看进程的内存占用情况
http://blog.csdn.net/xiyuan1999/article/details/8027386

linux服务器常用操作和命令
http://wiki.open.qq.com/wiki/faq/linux%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%B8%B8%E7%94%A8%E6%93%8D%E4%BD%9C%E5%92%8C%E5%91%BD%E4%BB%A4