Linux常见问题:为什么Linux系统在运行的程序不多的情况下显示的空闲内存这么少?事实上,Linux的内存管理与Windows是不同的。它会尝试缓存内存以提高读写性能,通常称为CacheMemory。比较老的资料会介绍,Linux的Cache占用多了也没关系,因为Linux会尽可能多的使用内存做缓存。但是缓存的回收也是需要资源的。一篇比较好的文章是Linux内存中的Cache真的可以被可怜的佐罗回收吗?.虽然大多数情况下我们看到Cache使用率高的时候是没有问题的,但是我们还是想搞清楚到底是哪个程序让Cache这么高,这不是一件容易的事情。内核模块在分配资源时,为了提高效率和资源利用率,都是通过Slab进行分配的。Slabs占用内存用于结构化缓存,通常会占用大量内存。不过借助slabtop工具,我们可以很方便的显示内核芯片缓存信息,可以更直观的显示/proc/slabinfo下的内容。#Showsthestatusofobjectsoccupiedinamachinecache$slabtop-scActive/TotalObjects(%used):856448/873737(98.0%)Active/TotalSlabs(%used):19737/19737(100.0%)Active/TotalCaches(%used):67/89(75.3%)Active/TotalSize(%used):141806.80K/145931.33K(97.2%)Minimum/Average/MaximumObject:0.01K/0.17K/8.00KOBJSACTIVEUSEOBJSIZESLABSOBJ/SLABCACHESIZENAME416949416949100%0.10K106913942764Kbuffer_head5616554598%2.00K3511611232Kkmalloc-20489114899098%1.02K294319408Kext4_inode_cache1240412404100%0.57K443287088Kradix_tree_node108001073199%0.58K400276400Kinode_cache312902964994%0.19K745425960Kdentry3552336294%1.00K111323552Kkmalloc-10241100105595%2.84K100113200Ktask_struct1649148189%1.88K97173104KTCP2700027000100%0.11K750363000Ksysfs_dir_cache1380126991%2.06K92152944Ksighand_cache虽然上面的命令显示了Cache中Slab的情况,但是还是没有显示什么程序占用的Cache.Solution1:UsePcstattoimplementAftersearching,Ifoundthatlinux-ftoolsisatoolthatcandisplaytheCacheoccupiedbyacertainfile,andfincoreisjustoneofitstools.$fincore[options]files...--pages=falseDonotprintpages--summarizeWhencomparingmultiplefiles,printasummaryreport--only-cachedOnlyprintstatsforfilesthatareactuallyincache.https://colobu.com/2017/03/07/what-is-in-linux-cached/root@xxxxxx:/var/lib/mysql/blogindex#fincore--pages=false--summarize--only-cached*statsforCLUSTER_LOG_2010_05_21.MYI:filesize=93840384,totalpages=22910,cachedpages=1,cachedsize=4096,cachedperc=0.004365statsforCLUSTER_LOG_2010_05_22.MYI:filesize=417792,totalpages=102,cachedpages=1,cachedsize=4096,cachedperc=0.980392statsforCLUSTER_LOG_2010_05_23.MYI:filesize=826368,totalpages=201,cachedpages=1,cachedsize=4096,cachedperc=0.497512statsforCLUSTER_LOG_2010_05_24.MYI:filesize=192512,totalpages=47,cachedpages=1,cachedsize=4096,cachedperc=2.127660statsforCLUSTER_LOG_2010_06_03.MYI:filesize=345088,totalpages=84,cachedpages=43,cachedsize=176128,cachedperc=51.190476statsforCLUSTER_LOG_2010_06_04.MYD:filesize=1478552,totalpages=360,cachedpages=97,cachedsize=397312,cachedperc=26.944444statsforCLUSTER_LOG_2010_06_04.MYI:filesize=205824,totalpages=50,cachedpages=29,cachedsize=118784,cachedperc=58.000000statsforCOMMENT_CONTENT_2010_06_03.MYI:filesize=100051968,totalpages=24426,cachedpages=10253,cachedsize=41996288,cachedperc=41.975764statsforCOMMENT_CONTENT_2010_06_04.MYD:filesize=716369644,totalpages=174894,cachedpages=79821,cachedsize=326946816,cachedperc=45.639645statsforCOMMENT_CONTENT_2010_06_04.MYI:filesize=56832000,totalpages=13875,cachedpages=5365,cachedsize=21975040,cachedperc=38.666667statsforFEED_CONTENT_2010_06_03.MYI:filesize=1001518080,totalpages=244511,cachedpages=98975,cachedsize=405401600,cachedperc=40.478751statsforFEED_CONTENT_2010_06_04.MYD:filesize=9206385684,totalpages=2247652,cachedpages=1018661,cachedsize=4172435456,cachedperc=45.321117statsforFEED_CONTENT_2010_06_04.MYI:filesize=638005248,totalpages=155763,cachedpages=52912,cachedsize=216727552,cachedperc=33.969556statsforFEED_CONTENT_2010_06_04.frm:filesize=9840,totalpages=2,cachedpages=3,cachedsize=12288,cachedperc=150.000000statsforPERMALINK_CONTENT_2010_06_03.MYI:filesize=1035290624,totalpages=252756,cachedpages=108563,cachedsize=444674048,cachedperc=42.951700statsforPERMALINK_CONTENT_2010_06_04.MYD:filesize=55619712720,totalpages=13579031,cachedpages=6590322,cachedsize=26993958912,cachedperc=48.533080statsforPERMALINK_CONTENT_2010_06_04.MYI:filesize=659397632,totalpages=160985,cachedpages=54304,cachedsize=222429184,cachedperc=33.732335statsforPERMALINK_CONTENT_2010_06_04.frm:filesize=10156,totalpages=2,cachedpages=3,cachedsize=12288,cachedperc=150.000000---totalcachedsize:32847278080fincore的工作原理是将指定文件对应的InodeData与Kernel的PageCacheTable进行比较,如果PageCacheTable有这个Inode信息,查找这个Inode对应的DataBlock的大小,因为Kernel的PageCacheTable只存放了引用DataBlock的名称而不是文件名,即文件的Inode信息。所以没有一个工具可以在一次运行中找出所有文件的缓存使用情况。所以使用linux-fincore这个工具只能加上文件名来判断文件是否被缓存,如果有,大小是多少。问题是您不能只猜测哪个文件被缓存或没有缓存。Shanker提供了一个脚本来解决这个问题,就是查看哪些进程使用的物理内存最多,找到该进程打开的文件,然后使用fincore查看这些文件的缓存使用情况。这种方法在大多数情况下可以找到占用大量Cache的程序和进程。脚本内容如下:#!/bin/bash#Author:Shanker#Time:2016/06/08#set-e#set-u#youhavetoinstalllinux-fincoreif[!-f/usr/local/bin/linux-fincore]thenecho"Youhaven'tstalledlinux-fincoreyet"exitfi#findthetop10processs'cachefileps-e-opid,rss|sort-nk2-r|head-10|awk'{print$1}'>/tmp/cache.pids#findalltheprocesss'cachefile#ps-e-opid>/tmp/cache.pidsif[-f/tmp/cache.files]thenecho"thecache.filesiseexist,removingnow"rm-f/tmp/cache.filesfiwhilereadlinedolsof-p$line2>/dev/null|awk'{print$9}'>>/tmp/cache.filesdone>/tmp/cache.fincorefidonelinux-fincore-s`cat/tmp/cache.fincore`rm-f/tmp/cache.{pids,files,fincore}不幸的是,不再维护linux-ftools。这个程序在新版本的操作系统上编译不好,所以这个方法失败了。再次谷歌搜索后,找到了pcstat这个工具。pcstat是用Go语言开发的,其功能与linux-ftools基本相同。项目地址:https://github.com/tobert/pcstat然后我修改了shanker的脚本,使用pcstat进行处理,这样就可以很好的发现Cache被占用的情况。修改后的脚本如下:#!/bin/bash#youhavetoinstallpcstatif[!-f/data0/brokerproxy/pcstat]thenecho"Youhaven'tinstalledpcstatyet"echo"run\"gogetgithub.com/tobert/pcstat\"toinstall"exitfi#findthetop10processs'cachefileps-e-opid,rss|sort-nk2-r|head-10|awk'{print$1}'>/tmp/cache.pids#findalltheprocesss'cachefile#ps-e-opid>/tmp/cache。pidsif[-f/tmp/cache.files]thenecho"thecache.filesisexist,removingnow"rm-f/tmp/cache.filesfiwhilereadlinedolsof-p$line2>/dev/null|awk'{print$9}'>>/tmp/cache.filesdone>/tmp/cache.pcstatfidone/data0/brokerproxy/pcstat`cat/tmp/cache.pcstat`rm-f/tmp/cache.{pids,files,pcstat}后的显示结果脚本运行成功如下:+----------------------------------------+----------------+------------+------------+--------+|名称|大小(字节)|页面|缓存|Percent||----------------------------------------+----------------+------------+----------+---------||/data0/abcasyouknow/0307/abc|10060771|2457|2457|100.000||/data0/abcasyouknow/0307/logs/abc.log|1860|1|1|100.000||/data0/abcasyouknow/0307/logs/uuid。日志|326326364|79670|79670|100.000||/usr/bin/bash|960384|235|194|082.553||/usr/lib/locale/locale-archive|106065056|25895|211|000.815||/usr/lib64/libnss_files-2.17.so|58288|15|15|100.000||/usr/lib64/libc-2.17.so|2107760|515|336|065.243||/usr/lib64/libdl-2.17.so|19512|5|5|100.000||/usr/lib64/libtinfo.so.5.9|174520|43|42|097.674||/usr/lib64/ld-2.17.so|164336|41|41|100.000||/usr/lib64/gconv/gconv-modules.cache|26254|7|7|100.000|+------------------------------------------+----------------+------------+-----------+--------+从结果可以看出,uuid.log占用了很多Cache。这个文件是打开的,程序一直在里面写入日志。Linux应该缓存它。方案二:使用vmtouch来实现除了上面提到的pcstat工具,还可以使用vmtouch来达到同样的目的。vmtouch是一个可以查询缓存文件和目录,并将文件推入缓存或从缓存中驱逐的工具。项目地址:https://github.com/hoytech/vmtouch安装Vmtouch$gitclonehttps://github.com/hoytech/vmtouch$cdvmtouch$make$sudomakeinstall使用Vmtouchvmtouch命令语法$vmtouchvmtouch:nofilesordirectoriesspecifiedvmtouchv1.0.2-theVirtualMemoryToucherbyUcachesttouchssystem[OPTIONS]...FILESORDIRECTORIES...Options:-ttouchpagesintomemory-eevictpagesfrommemory-llockpagesinphysicalmemorywithmlock(2)-Llockpagesinphysicalmemorywithmlockall(2)-ddaemonmode-mmaxfilesizetotouch-pusethespecifiedportioninsteadoftheentirefile-ffollowsymboliclinks-halsocounthardlinkedcopies-wwaituntilallpagesarelocked(onlyusefultogetherwith-d)-vverbose-qquiet2.一些使用该示例使用起来简单得多,因为vmtouch直接支持目录级查询。查看/tmp目录在内存中的缓存$vmtouch/tmp/vmtouch:WARNING:skippingnon-regularfile:/tmp/ssh-GgJnCEkWMQC2/agent.1068Files:17Directories:7ResidentPages:4780/478018M/18M100%Elapsed:0.001006seconds如果需要要查看更详细的信息,可以使用-v参数。$vmtouch-v/tmp/检查缓存了多少文件$vmtouch-v~/Downloads/phoronix-test-suite_6.0.1_all.deb/home/neo/Downloads/phoronix-test-suite_6.0.1_all.deb[]0/132Files:1Directories:0ResidentPages:0/1320/528K0%Elapsed:0.000117seconds缓存指定文件$vmtouch-vt~/Downloads/phoronix-test-suite_6.0.1_all.deb/home/neo/Downloads/phoronix-test-suite_6.0.1_all.deb[OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO]132/132Files:1Directories:0TouchedPages:132(528K)Elapsed:0.007935seconds驱逐缓存中指定的数据$vmtouch-ve~/Downloads/phoronix-test-suite_6.0.1_all.debEvicting/home/neo/Downloads/phoronix-test-suite_6.0.1_all.debFiles:1Directories:0EvictedPages:132(528K)Elapsed:0.000109seconds更具体的vmtouch的使用可以参考官网:https://hoytech.com/vmtouch/如果你有更多Linux下查看Cache或Buffer使用情况的方法,欢迎留言告诉我们!
