| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> linux下共享内存sharedMemory(shm)和内存映射memorymap的关系 -> 正文阅读 |
|
[系统运维]linux下共享内存sharedMemory(shm)和内存映射memorymap的关系 |
? ? ? ? 这一段因为持续使用共享内存和内存映射,最早的例子也是从网上找的,然后改了一下满足我们的需求,但底层的区别和联系没有细想。今天因为要测试给认知框架开发的数据共享库涉及到了共享内存,同事问这些事情,而前面看过system V、Posix、XSI的共享内存的关系,但是忘记了。于是又大概看了一下,并进行了仔细思考。 ? ? ? ? sharedMemory? ? ? ? 首先,我们要明确共享内存(shm)的应用场景是什么?也就是在什么场合使用共享内存。一般来说,多进程共享同一内存区域或者跨进程访问某个区域时才需要共享内存。也就是同一片内存,被多个进程共享。 ????????共享内存,顾名思义,就是预留出的内存区域,它允许一组进程对其访问。 共享内存是system v IPC中三种通信机制最快的一种,也是最简单的一种。对于进程来说, 获得共享内存后,他对内存的使用和其他的内存是一样的。由一个进程对共享内存所进行的 操作对其他进程来说都是立即可见的,因为每个进程只需要通过一个指向共享内存空间的指针就可以来读取 共享内存中的内容(说白了就好比申请了一块内存,每个需要的进程都有一个指针指向这个内存) 就可以轻松获得结果。 ? ? ? ? memoryMap? ? ? ? 内存映射,一般指的是为了加快文件操作,将文件系统上某个文件的一段内容映射到内存中,用户可以在核外地址空间直接读写内核地址空间的地址对应的内容,这样进程在读写文件时,少了一次拷贝开销。这个一般是用在一个进程内的。 ? ? ? ? 由此看来,sharedMemory用于多个进程共享同一块地址空间,实现多个人访问同一个区域,目的是共享。mmap内存映射的目的是加快访问速度。这两个并不冲突,所以可以组合到一起使用。 ? mmap的用途
????????就POSIX接口的共享内存来说,他们的底层都是调用mmap,不同的只是共享内存打开文件调用shm_open(),而内存映射调用open()。那shm_open有什么神奇的呢?看了下glibc2.29中的源码:
????????代码里赫然写着open,看来shm_open只不过是封装了一个更安全的open而已。 为什么共享内存一定要放在/dev/shm/下?????????上面代码中,shm_open传入的参数叫name,然而到open的时候却变成了shm_name,但是前后却找不到shm_name定义的地方。大佬们写的代码都这么神奇的吗?仔细一看,原来在上边的宏里:
????????宏中声明了shm_name,构造出shm_dir,shm_dir的内容就是/dev/shm/,之后通过和name拼接:
????????生成了shm_name。 ????????但是这只是解释了是怎么干的,却没有解释,为什么要这么干,为什么GlibC要在代码里写死把共享内存放在这个分区下呢? ????????/dev/shm/使用了一种特殊的文件系统tmpfs,它是虚拟的,并不是磁盘上的真实的分区,它如何快,如何好,如何厉害等等……通过df命令查看/dev/shm/分区,类型确实写着tmpfs,而使用文件内存映射生成的文件,却平平无奇,看不出有什么特殊的。莫非,共享内存和文件内存映射的区别在这里?共享内存使用了一种特殊的文件系统,而文件内存映射没有吗?但是他们明明传入mmap的参数也是一样的啊…也即是说内存映射和共享内存用的都是mmap,但叫法和用途却不同,使用的文件和涉及的文件系统也不同。我猜测tmpfs整个就构建在内核空间,而不是用户空间,所以多个进程才可以共享。 /dev/shm或者tmpfs? ? ? ? 内存文件系统tmpfs,在操作系统上有一个路径是/dev/shm,该目录下的文件都在内存中存储,断电后消失。如何打开/dev/shm下的文件呢?shm_open可以打开。就像open可以打开普通文件一样。因为文件系统在内存中,其操作读写也都在内存中,不存在写盘的操作,所以很快。
????????这段说tmpfs是一个文件系统,所有的文件都存在于虚拟内存中,物理磁盘上没有任何文件。如果把一个tmpfs实例解挂了,其中存储的内容就丢失了。这段和网上说的如出一辙,对一个新手来说一样的云里雾里。什么叫在虚拟内存里?虚拟内存不就是个抽象吗?顶多就是内核的一个数据结构啊。没有文件在磁盘上?那文件去哪了?在物理内存上吗?不大对啊,物理内存直接当硬盘使吗?
????????这段说tmpfs文件系统完全存活在page cache和swap中,当前在内存中的tmpfs页会显示为cacheed,不会被显示为shared或其他。可以通过df和du命令查看tmpfs实例真实使用的物理内存+swap大小。 ????????随便找一台测试机器,用free -g命令看下:
shared为0,buff/cache为90G 然后删除/dev/shm/下的几个文件看看:
????????嗯,大小果真对的上,证明文中所言非虚,tmpfs文件系统中的实例,会显示在cache中,而不是shared,尽管我们会管这个叫”共享内存“。
????????这段是说着,内核内部会有一个挂载,你是看不到的,当你使用匿名共享内存映射或者System V共享内存的时候,会用到这个隐藏的挂载。而且,即使内核中的编译选项CONFIG_TMPFS没有设置,tmpfs那没有编译,这个内部隐藏的机制依然有效。 ????????这点对我们来说意义重大,这意味着,共享内存和tmpfs文件系统,都是使用了内核提供的机制来实现的,共享内存的实现,和tmpfs系统是没有依赖关系的。那么这个机制到底是啥呢?到底是怎么实现的呢?在此挖个坑。
????????这段就更直白了,glibc在实现POSIX共享内存时,会预设tmpfs文件系统挂载在/dev/shm/,所以用POSIX共享内存的时候,记得在/etc/fstab里编辑一下,把这个分区给挂载上。 共享内存和文件内存映射有什么区别?????????首先是共享内存和文件内存映射的接口、用法不一样,GLIBC的POSIX的共享内存实现会默认把共享内存文件放在/dev/shm/分区下,如果没有这个分区,需要手动挂载一下。 ????????然后就是共享内存和文件内存映射,在内核中的实现原理,都使用了内核的cache和swap机制,完全没有区别。 ????????虽然System V与POSIX共享内存都是通过tmpfs实现,但是受的限制却不相同。也就是说/proc/sys/kernel/shmmax只会影响SYS V共享内存,/dev/shm只会影响Posix共享内存。实际上,System V与Posix共享内存本来就是使用的两个不同的tmpfs实例(instance)。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 16:53:24- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |