导读 | 大家可能有遇到类似的场景,想要对机器进行压测模拟 OOM 的场景,但是无奈机器的规格实在太高,若用代码去实现,大家可以想象一下如何实现?那么有没有好有的办法,不用写代码,用几个简单的命令直接就可以向机器申请内存呢?或者更极端点,直接把机器的内存给榨干了。。 |
若你经常使用 linux,你会发现 df -Th 后,一定会有 tmpfs 类型的文件系统挂载在 /dev/shm 下面,虽然你大概率不会关注到它。
$?df?-Th?? Filesystem?????Type??????Size??Used?Avail?Use%?Mounted?on?? devtmpfs???????devtmpfs??910M?????0??910M???0%?/dev?? tmpfs??????????tmpfs?????919M?????0??919M???0%?/dev/shm?? tmpfs??????????tmpfs?????919M??896K??918M???1%?/run?? tmpfs??????????tmpfs?????919M?????0??919M???0%?/sys/fs/cgroup?? /dev/vda1??????ext4???????40G???11G???27G??28%?/?? tmpfs??????????tmpfs?????184M?????0??184M???0%?/run/user/0
而这个 tmpfs 就是明哥今天要介绍的主角。
tmpfs,顾名思义,是临时文件系统,是一种基于内存的文件系统。
它和虚拟磁盘 ramdisk比较类似像,但不完全相同,和ramdisk一样,tmpfs可以使用RAM,但它也可以使用swap分区来存储,而且传统的ramdisk是个块设备,要用mkfs来格式化它,才能真正地使用它;而tmpfs是一个文件系统,并不是块设备,只是安装它,就可以使用了。tmpfs是最好的基于RAM的文件系统。
这意味着,你往挂载了 tmpfs 的目录下写入的文件,都会直接写入内存中。
假如你想占用机器 10G 的内存,那我只要先创建一个临时目录 /tmp/memory ,并指定 tmpfs 的文件系统类型及大小 10240M 挂载到该目录下。
$?mount?-t?tmpfs?-o?size=10240M?tmpfs?/tmp/memory
接着咱使用 dd 命令,往该目录下写入多少内容,就会占用多少内存,由于我们的目的是占用内存,因此 if 直接使用 /dev/zero
$?dd?if=/dev/zero?of=/tmp/memory/block
当 dd 写入完成后,你再使用 free 去查看可用内存,会发现剩余的内存可分配的内存少了 10G。
如果你想用完机器的所有内存,完全可以在 mount 的时候,指定 size 为机器的内存大小,但你要清楚你在做什么,否则执行完 dd ,你的机器可能就挂了。
利用上面这个方法,其实还可以做更多的事情,比如你在机器你有两个 NUMA Node ,但你只想占用 NUMA Node 0 的内存,那就可以指定 NUMA Node 0 的内存,怎么办呢?
首先利用 lscpu 找到 NUMA Node 0 上的所有 cpu 核
$?node0_cpus=$(lscpu?|?grep?"NUMA?node0"?|?awk?'{print?$NF}')
然后使用 taskset 工具加 -c 参数来指定对应的 cpu 核来执行创建 tmpfs 目录和 dd? 的过程
$?cat?>?/root/mem_alloc.sh?<<EOF?? #!/bin/bash?? tmpdir=`mktemp`?? mount?-t?tmpfs?-o?size=1024M?tmpfs?${tmpdir}?? dd?if=/dev/zero?of=${tmpdir}/block?? EOF?? $?taskset?-c?"${node0_cpus}"?sh?/root/mem_alloc.sh
执行完成后,如果你所占用的内存,没有超过 NUMA Node 0 的本地内存,那么你使用 numactl 就会发现上面命令都只占用了 NUMA Node0 的内存。