Linux系统中的tmpfs、/dev/shm、tmp以及共享内存机制

共享内存允许两个或更多进程访问同一块内存。

tmpfs

tmpfs一种基于内存的临时文件系统,tmpfs可以使用RAM,但它也可以使用swap分区来存储。传统的ramdisk是个块设备,要用mkfs来格式化它,才能真正地使用它;tmpfs是一个文件系统,并不是块设备,安装即可以使用。tmpfs是最好的基于RAM的文件系统。

  • 特征:
    • 动态文件系统大小
    • 存取速度快

/dev/shm

是利用内存虚拟出来的磁盘空间。通常是内存空间大小的一半,该目录下创建的文件存取速度优于普通硬盘挂载的目录下的文件,该目录下的文件在机器重启时会丢失。

/tmp目录

存放临时文件的目录。由于通常/dev/shm挂载在/tmp目录下,该目录会被不同用户读写,因此该目录的权限建议设置成777
之前就在生产环境中遇到过/tmp目录权限被旁路流程误修改为755,导致普通用户启动的C++的应用无法写入共享内存,导致线上服务异常的惨痛教训。希望大家吸取教训。
这种目录权限导致的问题,恢复较为容易,但是定位问题原因较为复杂,由于之前的代码中没有调试逻辑,出现问题时,开发临时新上了一版代码增加了详细的错误输出,最后才定位到共享内存写入失败导致,此过程花费相对较长的时间。

  • 文件系统挂载关系
    1
    2
    3
    # cat /etc/fstab |egrep "tmp|shm"
    tmpfs /dev/shm tmpfs defaults 0 0
    /dev/shm /tmp none rw,bind 0 0

Linux的两种共享内存机制:

  • POSIX共享内存(结合内存映射mmap使用)
    • mmap映射的内存是非持久化的,随着进程关闭,映射会随即失效。
    • mmap内存映射机制标准的系统调用,分为:
      • 匿名映射
      • 文件映射,又分为:
        • MAP_PRIVATE
        • MAP_SHARED
  • System V共享内存(经典方案)
    • sysv shm是持久化的,除非被进程明确的删除,否则在系统关机前始终存在于内存中。

虽然System V与POSIX共享内存都是通过tmpfs实现,但由于内核在mount tmpfs时,指定了MS_NOUSER,所以该tmpfs没有大小限制。因此/proc/sys/kernel/shmmax只会限制System V共享内存,/dev/shm只限制Posix共享内存,默认是物理内存的一半。

  • System V共享内存的最大值

    1
    2
    # cat /proc/sys/kernel/shmmax
    68719476736
  • /dev/shm空间大小设定

    1
    mount -t tmpfs -o size=2G tmpfs -o remount /dev/shm

修改tmpfs大小

  • /etc/fstab 字段介绍

    1
    2
    /etc/fstab
    # <file system> <dir> <type> <options> <dump> <pass>
    • file system: 要挂载的分区或存储设备
    • dir: file systems的挂载位置
    • type: 要挂载设备或是分区的文件系统类型
      • ext2, ext3, ext4, reiserfs, xfs, jfs, smbfs, iso9660, vfat, ntfs, swap 及 auto
    • options: 挂载时使用的参数
      • defaults
    • dump: dump工具通过它决定何时作备份
      • 0和1,0表示忽略,1则进行备份。大部分的用户是没有安装 dump 的,对他们而言应设为 0。
    • pass fsck 读取 pass的数值来决定需要检查的文件系统的检查顺序。允许的数字是0,1,和2。
      • 根目录应当获得最高的优先权 1,
      • 其它所有需要被检查的设备设置为 2.
      • 0表示设备不会被 fsck 所检查。
  • centos5修改tmpfs大小

    1
    2
    3
    4
    cat /etc/fstab
    tmpfs /dev/shm tmpfs defaults 0 0 //修改这行不起作用
    /dev/shm /tmp none rw,bind,size=55g 0 0

  • centos6/7修改tmpfs大小

    1
    2
    3
    cat /etc/fstab
    tmpfs /dev/shm tmpfs defaults,size=30g 0 0
    /dev/shm /tmp none rw,bind 0 0 // 修改这行不起作用
  • 挂载命令

    1
    2
    mount -a        //加载文件"/etc/fstab"中描述的所有文件系统。
    mount -o remount /dev/shm //重新加载设备
    • 要直接执行 mount -a 命令,因为可能造成无法访问当前目录中的文件(比如你应该保证 lockfiles 的正常存在)。
    • 然而,如果它们都是空的,那么就可以直接执行 mount -a 而不必重启电脑。
    • 应用更改后,可以通过 findmnt 检查是否生效:
      1
      findmnt --target /tmp
    • tmpfs 可以设置成比物理内存大,但是只能存储小于物理内存空间的数据,之后会出现登录掉线等异常.