理解/dev/shm目录
dev == device
shm == shared memory
linux中/dev目录下一般都是一些设备文件,例如磁盘、内存、摄像头等。
/dev/shm是linux下一个非常有用的目录,它是linux操作系统利用内存虚拟出来的一个目录,这个目录中的文件都是保存在内存中,效率非常高。或者说这个目录用于内存映射。也就是说往这个目录写东西,都会写到内存里,不会持久化到磁盘。系统重启以后,文件都消失。其大小是非固定的,不是预先分配好的内存来存储。它的默认大小是内存的一半,被它占用的内存不会被系统回收重新划分。
它本质上是所谓的文件系统tmpfs,这是一个将所有文件和文件夹写到虚拟内存中而不是实际写到磁盘中的虚拟文件系统。这意味中tmpfs中所有的内容都是临时的,在tmpfs卸载、系统重启或者电源切断后内容都将会丢失。技术的角度上来说,tmpfs将所有的内容放在内核内部缓存中并且会调整大小来容纳文件,并可从交换空间中交换出不需要的页。由此可见,tmpfs主要存储暂存的文件。它有以下优势:
- 动态文件系统的大小,/dev/shm/需要注意的一个是容量问题,在linux下,它默认情况下是内存的一半大小,使用df -h命令可以看到。但它并不会真正的占用这块内存,如果/dev/shm/下没有任何文件,它占用的内存实际上就是0字节;如果它最大为1G,里头放有 100M文件,那剩余的900M仍然可为其它应用程序所使用,但它所占用的100M内存,是绝不会被系统回收重新划分的
- tmpfs 的另一个主要的好处是它闪电般的速度。因为典型的 tmpfs 文件系统会完全驻留在 RAM 中,读写几乎可以是瞬间的。
- tmpfs 数据在重新启动之后不会保留,因为虚拟内存本质上就是易失的。所以有必要做一些脚本做诸如加载、绑定的操作。
注:
- 在Centos和Redhat下,/dev/shm目录是一个链接,指向/run/shm目录,在Ubuntu系统下tmpfs文件系统对应的是/run/shm目录,可以使用df命令查看
- 在Docker容器中,/dev/shm/目录默认情况下是64MB。
简要说明
操作系统环境:
> cat /etc/centos-release
CentOS Linux release 7.1.1503 (Core)
我们先来看一下使用df -h命令可以看到什么。
> df -h
Filesystem Size Used Avail Use% Mounted on
overlay 99G 4.2G 90G 5% /
tmpfs 32G 0 32G 0% /dev
tmpfs 32G 0 32G 0% /sys/fs/cgroup
/dev/vdb1 197G 177G 11G 95% /data/logs
/dev/vda1 99G 4.2G 90G 5% /etc/hosts
shm 64M 16K 64M 1% /dev/shm
其中,/dev/shm
就是共享内存,它使用内存虚拟出一个文件路径,可以视为文件进行访问。它的容量默认内存的一半。
目录查看
查看/dev/shm目录的文件,通常情况下,该目录没有文件。
> ls /dev/shm
容量扩容
如果需要使用到这个目录,并且默认的大小不够使用,而其他程序占用的内存又比较少的时候,可以修改其占用的最大内存。
容量扩容原理很简单,对其进行重新挂载即可,挂载的时候指定挂载参数。
这里对/dev/shm进行了重新挂载,并修改其大小为5G。
> sudo mount -o size=5128M -o remount /dev/shm
> df -h //查看确认
Filesystem Size Used Avail Use% Mounted on
overlay 99G 4.2G 90G 5% /
tmpfs 32G 0 32G 0% /dev
tmpfs 32G 0 32G 0% /sys/fs/cgroup
/dev/vdb1 197G 177G 11G 95% /data/logs
/dev/vda1 99G 4.2G 90G 5% /etc/hosts
shm 5.1G 64M 5.0G 2% /dev/shm
默认情况下,该目录的inode数量很低,一般都要调高些。下面的命令将共享目录最大容量调到1.5G,并且inode数量调到1000000,这意味着大致可存入最多一百万个小文件。
#mount -o size=1500M -o nr_inodes=1000000 -o noatime,nodiratime -o remount /dev/shm
如果需要永久修改/dev/shm的值,需要修改/etc/fstab
tmpfs /dev/shm tmpfs defaults,size=1.5G 0 0
重新挂载
> mount -o remount /dev/shm
文件测试
现在我们在/dev/shm目录中创建一个大小为1GB和一个大小为2GB的文件。
> dd if=/dev/zero of=/dev/shm/123.random bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.458872 s, 2.3 GB/s
> dd if=/dev/zero of=/dev/shm/1234.random bs=1M count=2048
2048+0 records in
2048+0 records out
2147483648 bytes (2.1 GB) copied, 0.851609 s, 2.5 GB/s
> df -h //查看确认
Filesystem Size Used Avail Use% Mounted on
overlay 99G 4.2G 90G 5% /
tmpfs 32G 0 32G 0% /dev
tmpfs 32G 0 32G 0% /sys/fs/cgroup
/dev/vdb1 197G 177G 11G 95% /data/logs
/dev/vda1 99G 4.2G 90G 5% /etc/hosts
shm 5.1G 3.1G 2.1G 60% /dev/shm //总大小5.1GB,已使用3.1GB
也可以使用查看内存的命令free来查看,这里显示总内存为64263MB,已使用1069MB,共享内存(shared)使用了3145MB。
> free -m
total used free shared buff/cache available
Mem: 64263 1069 1558 3145 61635 59468
Swap: 0 0 0
> ls /dev/shm
123.random 1234.random
> rm -f /dev/shm/1234.random //删除2GB的1234.random文件
> free -m //共享内存使用降低到1097MB
total used free shared buff/cache available
Mem: 64263 1072 3606 1097 59584 61513
Swap: 0 0 0
> rm -f /dev/shm/1234.random // 删除1GB的123.random文件
> free -m -h //共享内存使用降低到73MB
total used free shared buff/cache available
Mem: 62G 1.0G 4.5G 73M 57G 61G
Swap: 0B 0B 0B
# df -h //查看磁盘空间
Filesystem Size Used Avail Use% Mounted on
overlay 99G 4.2G 90G 5% /
tmpfs 32G 0 32G 0% /dev
tmpfs 32G 0 32G 0% /sys/fs/cgroup
/dev/vdb1 197G 177G 11G 95% /data/logs
/dev/vda1 99G 4.2G 90G 5% /etc/hosts
shm 5.1G 16K 5.1G 1% /dev/shm //总大小5.1GB,已使用16KB
应用场景
对于一些iops较高的场景,可以开启写入缓存或者使用/dev/shm方式减少IOPS。结合场景,充分利用内存是/dev/shm的精髓。
应用案例:
- Nginx
比如nginx的几个temp目录可以指向到这里,一些不重要的日志可以接受一定的丢失场景下,放到这里对性能也有显著的提升。对于nginx来说,开启日志的buffer也会有很明显的提升。 - Oracle
Oracle 11g的AMM(Automatic Memory Management特性)内存管理模式就是使用/dev/shm
应用方法
一般地,首先在/dev/shm建个tmp文件夹,然后与实际/tmp绑定。
> mkdir /dev/shm/tmp
> chmod 1777 /dev/shm/tmp
> mount –bind /dev/shm/tmp /tmp
> ls -ld /tmp
注意:在使用mount –bind olderdir newerdir
命令来挂载一个目录到另一个目录后,newerdir的权限和所有者等所有信息会发生变化。挂载后的目录除了名称外,继承了被挂载目录的所有属性。
将/dev/shm与/tmp绑定后,常用的应用示例包括:
1.将squid的缓存目录cache_dir放到/tmp下
>vi /etc/squid/squid.conf //修改成 cache_dir ufs /tmp 256 16 256
这里的第一个256表示使用256M内存,重启一下squid服务,这样缓存目录都放在了tmpfs文件中了,速度不用说吧。
2.将php的session文件放在/tmp下
对于一个访问量大的以apache php的网站,可能tmp下的临时文件都会很多,比如seesion或者一些缓存文件,那么你可以把它保存到tmpfs文件。保存seesion的方法很简单了:只要修改php.ini就行了,通过phpinfo测试文件查看你的php session存储位置,如果不在/tmp下,修改php.ini文件,修改如下:
session.save_path = “/tmp”
3.将服务的socket文件放在/tmp下
如nginx.socket和mysql.sock。
CentO S7拓展应用方法 & 翻译稿
方法1. systemctl命令
你可以使用systemctl命令在tmp目录启用tmpfs, 首先用下面的命令来检查这个特性是否可用:
# systemctl is-enabled tmp.mount
disabled
这会显示当先的状态,(如果未启用,)你可以使用下面的命令来启用它:
# systemctl enable tmp.mount
ln -s '/usr/lib/systemd/system/tmp.mount' '/etc/systemd/system/local-fs.target.wants/tmp.mount'
这会让系统控制/tmp目录并在该目录下挂载一个tmpfs文件系统。
方法2. 手动挂载/tmp文件系统
你可以在/etc/fstab中添加下面这行,来手工在/tmp下挂载 tmpfs。
tmpfs /tmp tmpfs size=512m 0 0
接着运行这条命令
# mount –a
这应该就会在df -h中显示tmpfs了,同样也会在你下次重启时自动挂载。
# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 99G 4.2G 90G 5% /
tmpfs 32G 0 32G 0% /dev
tmpfs 32G 0 32G 0% /sys/fs/cgroup
/dev/vdb1 197G 177G 11G 95% /data/logs
/dev/vda1 99G 4.2G 90G 5% /etc/hosts
shm 5.1G 16K 5.1G 1% /dev/shm
tmpfs 512M 0 512M 0% /tmp //新创建的/tmp
方法3. 立即创建tmpfs
如果由于一些原因,你需要在一个文件夹下立即创建tmpfs,你可以使用下面的命令:
# mount -t tmpfs -o size=1G tmpfs /mnt/mytmpfs
当然你可以在size选项中指定你希望的大小和希望的挂载点,只要记住是有效的目录就行了。
基于shm的开源库
- tmpfs-mysql - Speed up your tests using MySQL/MariaDB server with tmpfs datadir. It is a Bash script instantiating a mysql server with datadir set to a tmpfs mounted filesystem
- mem-shm - Node.JS module which allows you to store, key => value to /dev/shm/
- FastMmapMQ - Fast Message queue module, witch can pass messages between different processes, for Python, nodejs and c written in C using a memory mapped file in /dev/shm. Currently this only works on Linux because of requirements on /dev/shm and procfs with /proc/{PID}/fd.
- greenbox - one writer and multireader buffer, using shared memory and /dev/shm, python