shm == shared memory
linux中/dev目录下一般都是一些设备文件,例如磁盘、内存、摄像头等。
/dev/shm是linux下一个非常有用的目录,它是linux *** 作系统利用内存虚拟出来的一个目录,这个目录中的文件都是保存在内存中,效率非常高。或者说这个目录用于内存映射。也就是说往这个目录写东西,都会写到内存里,不会持久化到磁盘。系统重启以后,文件都消失。其大小是非固定的,不是预先分配好的内存来存储。它的默认大小是内存的一半,被它占用的内存不会被系统回收重新划分。
它本质上是所谓的文件系统tmpfs,这是一个将所有文件和文件夹写到虚拟内存中而不是实际写到磁盘中的虚拟文件系统。这意味中tmpfs中所有的内容都是临时的,在tmpfs卸载、系统重启或者电源切断后内容都将会丢失。技术的角度上来说,tmpfs将所有的内容放在内核内部缓存中并且会调整大小来容纳文件,并可从交换空间中交换出不需要的页。由此可见,tmpfs主要存储暂存的文件。它有以下优势:
注:
*** 作系统环境:
我们先来看一下使用df -h命令可以看到什么。
其中, /dev/shm 就是共享内存,它使用内存虚拟出一个文件路径,可以视为文件进行访问。它的容量默认内存的一半。
查看/dev/shm目录的文件,通常情况下,该目录没有文件。
如果需要使用到这个目录,并且默认的大小不够使用,而其他程序占用的内存又比较少的时候,可以修改其占用的最大内存。
容量扩容原理很简单,对其进行重新挂载即可,挂载的时候指定挂载参数。
这里对/dev/shm进行了重新挂载,并修改其大小为5G。
默认情况下,该目录的inode数量很低,一般都要调高些。下面的命令将共享目录最大容量调到1.5G,并且inode数量调到1000000,这意味着大致可存入最多一百万个小文件。
如果需要永久修改/dev/shm的值,需要修改/etc/fstab
重新挂载
现在我们在/dev/shm目录中创建一个大小为1GB和一个大小为2GB的文件。
也可以使用查看内存的命令free来查看,这里显示总内存为64263MB,已使用1069MB,共享内存(shared)使用了3145MB。
对于一些iops较高的场景,可以开启写入缓存或者使用/dev/shm方式减少IOPS。结合场景,充分利用内存是/dev/shm的精髓。
应用案例:
一般地,首先在/dev/shm建个tmp文件夹,然后与实际/tmp绑定。
注意:在使用 mount –bind olderdir newerdir 命令来挂载一个目录到另一个目录后,newerdir的权限和所有者等所有信息会发生变化。挂载后的目录除了名称外,继承了被挂载目录的所有属性。
将/dev/shm与/tmp绑定后,常用的应用示例包括:
1.将squid的缓存目录cache_dir放到/tmp下
这里的第一个256表示使用256M内存,重启一下squid服务,这样缓存目录都放在了tmpfs文件中了,速度不用说吧。
2.将php的session文件放在/tmp下
对于一个访问量大的以apache php的网站,可能tmp下的临时文件都会很多,比如seesion或者一些缓存文件,那么你可以把它保存到tmpfs文件。保存seesion的方法很简单了:只要修改php.ini就行了,通过phpinfo测试文件查看你的php session存储位置,如果不在/tmp下,修改php.ini文件,修改如下:
3.将服务的socket文件放在/tmp下
如nginx.socket和mysql.sock。
你可以使用systemctl命令在tmp目录启用tmpfs, 首先用下面的命令来检查这个特性是否可用:
这会显示当先的状态,(如果未启用,)你可以使用下面的命令来启用它:
这会让系统控制/tmp目录并在该目录下挂载一个tmpfs文件系统。
你可以在/etc/fstab中添加下面这行,来手工在/tmp下挂载 tmpfs。
接着运行这条命令
这应该就会在df -h中显示tmpfs了,同样也会在你下次重启时自动挂载。
如果由于一些原因,你需要在一个文件夹下立即创建tmpfs,你可以使用下面的命令:
当然你可以在size选项中指定你希望的大小和希望的挂载点,只要记住是有效的目录就行了。
/dev/shm/是一个设备文件,它使用就是tmpfs文件系统(注意:在CentOS和RedHat下,/dev/shm目录是一个链接,指向/run/shm目录,在Ubuntu系统下tmpfs文件系统对应的是/run/shm目录,可以使用df命令查看)。
因为 /dev/shm/这个目录不在硬盘上,而是在内存里,它就所谓的tmpfs。在Redhat/CentOS等linux发行版中默认大小为物理内存的一半。
tmpfs是Linux/Unix系统上的一种基于内存的文件系统。tmpfs可以使用您的内存或swap分区来存储文件。由此可见,tmpfs主要存储暂存的文件。它有如下2个优势:
1)动态文件系统
2)闪电般的速度,因为典型的 tmpfs 文件系统会完全驻留在内存 RAM 中,读写几乎可以是瞬间的。
扩展资料
虚拟内存
Linux内核的虚拟内存资源同时来源于您的RAM和交换分区。内核中的VM子系统将这些资源分配到系统中的其它部分,并负责在后台管理这些资源,通常是透明地将RAM页移动到交换分区或从交换分区到RAM页。
tmpfs文件系统需要VM子系统的页面来存储文件。tmpfs自己并不知道这些页面是在交换分区还是在RAM中;做这种决定是VM子系统的工作。tmpfs文件系统所知道的就是它正在使用某种形式的虚拟内存。
不同于大多数“标准的”文件系统,如ext3、ReiserFS和其它一些系统,tmpfs并不是存在于一个底层块设备上面。因为tmpfs是直接建立在VM之上的,您用一个简单的mount命令就可以创建tmpfs文件系统了。
参考资料来源:百度百科—tmpfs
关于 Linux 共享内存,写得最好的应该是宋宝华的 《世上最好的共享内存》 一文。
本文可以说是对这篇文章的学习笔记,顺手练习了一下 rust libc —— shichaoyuan/learn_rust/linux-shmipc-demo
按照宋宝华的总结,当前有四种主流的共享内存方式:
前两种方式比较符合传统的用法,共享内存做为进程间通信的媒介。
第三种方式更像是通过传递内存“句柄”进行数据传输。
第四种方式是为设备间传递数据设计,避免内存拷贝,直接传递内存“句柄”。
这里尝试了一下第二种和第三种方式。
这套 API 应该是最普遍的 —— shm_open + mmap,本质上来说 Aeron 也是用的这种方式(关于 Aeron 可以参考 我之前的文章 )。
看一下 glibc 中 shm_open 函数的实现就一清二楚了:
shm_open 函数就是在 /dev/shm 目录下建文件,该目录挂载为 tmpfs,至于 tmpfs 可以简单理解为存储介质是内存的一种文件系统,更准确的理解可以参考官方文档 tmpfs.txt 。
然后通过 mmap 函数将 tmpfs 文件映射到用户空间就可以随意 *** 作了。
优点:
这种方式最大的优势在于共享的内存是有“实体”(也就是 tmpfs 中的文件)的,所以多个进程可以很容易通过文件名这个信息构建共享内存结构,特别适合把共享内存做为通信媒介的场景(例如 Aeron )。
缺点:
如果非要找一个缺点的话,可能是,文件本身独立于进程的生命周期,在使用完毕后需要注意删除文件(仅仅 close 是不行的),否则会一直占用内存资源。
memfd_create 函数的作用是创建一个匿名的文件,返回对应的 fd,这个文件当然不普通,它存活在内存中。更准确的理解可以参考官方文档 memfd_create(2) 。
直观理解,memfd_create 与 shm_open 的作用是一样的,都是创建共享内存实体,只是 memfd_create 创建的实体是匿名的,这就带了一个问题:如何让其它进程获取到匿名的实体?shm_open 方式有具体的文件名,所以可以通过打开文件的方式获取,那么对于匿名的文件怎么处理呢?
答案是:通过 Unix Domain Socket 传递 fd。
rust 的 UDS 实现:
rust 在 std 中已经提供了 UDS 的实现,但是关于传递 fd 的 send_vectored_with_ancillary 函数还属于 nightly-only experimental API 阶段。所以这里使用了一个三方 crate —— sendfd ,坦白说可以自己实现一下,使用 libc 构建好 SCM_RIGHTS 数据,sendmsg 出去即可,不过细节还是挺多,我这里就放弃了。
这套 API 设计更灵活,直接拓展了我的思路,本来还是受限于 Aeron 的用法,如果在这套 API 的加持下,是否可以通过传递数据包内存块(fd)真正实现零拷贝呢?
优点:
灵活。
缺点:
无
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)