0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

世上最好的共享内存(Linux共享内存最透彻的一篇)上集

Linux阅码场 来源:Linuxer 2019-11-29 14:29 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

共享单车、共享充电宝、共享雨伞,世间的共享有千万种,而我独爱共享内存。

早期的共享内存,着重于强调把同一片内存,map到多个进程的虚拟地址空间(在相应进程找到一个VMA区域),以便于CPU可以在各个进程访问到这片内存。

现阶段广泛应用于多媒体、Graphics领域的共享内存方式,某种意义上不再强调映射到进程虚拟地址空间的概念(那无非是为了让CPU访问),而更强调以某种“句柄”的形式,让大家知道某一片视频、图形图像数据的存在并可以借助此“句柄”来跨进程引用这片内存,让视频encoder、decoder、GPU等可以跨进程访问内存。所以不同进程用的加速硬件其实是不同的,他们更在乎的是可以通过一个handle拿到这片内存,而不再特别在乎CPU访问它的虚拟地址(当然仍然可以映射到进程的虚拟地址空间供CPU访问)。

只要内存的拷贝(memcpy)仍然是一个占据内存带宽、CPU利用率的消耗大户存在,共享内存作为Linux进程间通信、计算机系统里各个不同硬件组件通信的最高效方法,都将持续繁荣。关于内存拷贝会大多程度地占据CPU利用率,这个可以最简单地尝试拷贝1080P,帧率每秒60的电影画面,我保证你的系统的CPU,蛋会疼地不行。

我早就想系统地写一篇综述Linux里面各种共享内存方式的文章了,但是一直被带娃这个事业牵绊,今日我决定顶着娃娃们的山呼海啸,也要写一篇文章不吐不快。

共享内存的方式有很多种,目前主流的方式仍然有:

共享内存的方式

1.基于传统SYS V的共享内存;

2.基于POSIXmmap文件映射实现共享内存;

3.通过memfd_create()和fd跨进程共享实现共享内存;

4.多媒体、图形领域广泛使用的基于dma-buf的共享内存。

共享内存

SYS V共享内存

历史悠久、年代久远、API怪异,对应内核代码linux/ipc/shm.c,当你编译内核的时候不选择CONFIG_SYSVIPC,则不再具备此能力。

你在Linux敲ipcs命令看到的share memory就是这种共享内存:

下面写一个最简单的程序来看共享内存的写端sw.c:

以及共享内存的读端sr.c:

编译和准备运行:

在此之前我们看一下系统的free:

下面运行sw和sr:

我们发现sr打印出来的和sw写进去的是一致的。这个时候我们再看下free:

可以看到used显著增大了(711632 -> 715908), shared显著地增大了(2264-> 6360),而cached这一列也显著地增大326604->330716。

我们都知道cached这一列统计的是file-backed的文件的page cache的大小。理论上,共享内存属于匿名页,但是由于这里面有个非常特殊的tmpfs(/dev/shm指向/run/shm,/run/shm则mount为tmpfs):

所以可以看出tmpfs的东西其实真的是有点含混:我们可以理解它为file-backed的匿名页(anonymous page),有点类似女声中的周深。前面我们反复强调,匿名页是没有文件背景的,这样当进行内存交换的时候,是与swap分区交换。磁盘文件系统里面的东西在内存的副本是file-backed的页面,所以不存在与swap分区交换的问题。但是tmpfs里面的东西,真的是在统计意义上统计到page cache了,但是它并没有真实的磁盘背景,这又和你访问磁盘文件系统里面的文件产生的page cache有本质的区别。所以,它是真地有那么一点misc的感觉,凡事都没有绝对,唯有变化本身是不变的。

也可以通过ipcs找到新创建的SYS V共享内存:

POSIX共享内存

我对POSIX shm_open()、mmap () API系列的共享内存的喜爱,远远超过SYS V 100倍。原谅我就是一个懒惰的人,我就是讨厌ftok、shmget、shmat、shmdt这样的API。

上面的程序如果用POSIX的写法,可以简化成写端psw.c:

读端:

编译和执行:

这样我们会在/dev/shm/、/run/shm下面看到一个文件:

坦白讲,mmap、munmap这样的API让我找到了回家的感觉,刚入行做Linux的时候,写好framebuffer驱动后,就是把/dev/fb0 mmap到用户空间来操作,所以mmap这样的 API,真的是特别亲切,像亲人一样。

当然,如果你不喜欢shm_open()这个API,你也可以用常规的open来打开文件,然后进行mmap。关键的是mmap,wikipedia如是说:

mmap

In computing, mmap(2) is a POSIX-compliant Unix system call that maps files or devices into memory. It is a method of memory-mapped file I/O. It implements demand paging, because file contents are not read from disk directly and initially do not use physical RAM at all. The actual reads from disk are performed in a "lazy" manner, after a specific location is accessed. After the memory is no longer needed, it is important to munmap(2) the pointers to it. Protection information can be managed using mprotect(2), and special treatment can be enforced using madvise(2).

POSIX的共享内存,仍然符合我们前面说的tmpfs的特点,在运行了sw,sr后,再运行psw和psr,我们发现free命令再次戏剧性变化:

请将这个free命令的结果与前2次的free结果的各个字段进行对照:

第3次比第2次的cached大了这么多?是因为我编写这篇文章边在访问磁盘里面的文件,当然POSIX的这个共享内存本身也导致cached增大了。

memfd_create

如果说POSIX的mmap让我找到回家的感觉,那么memfd_create()则是万般惊艳。见过这种API,才知道什么叫天生尤物——而且是尤物中的尤物,它完全属于那种让码农第一眼看到就会两眼充血,恨不得眼珠子夺眶而出贴到它身上去的那种API;一般人见到它第一次,都会忽略了它的长相,因为它的身材实在太火辣太抢眼了。

先不要浮想联翩,在所有的所有开始之前,我们要先提一下跨进程分享fd(文件描述符,对应我们很多时候说的“句柄”)这个重要的概念。

众所周知,Linux的fd属于一个进程级别的东西。进入每个进程的/proc/pid/fd可以看到它的fd的列表:

这个进程的0,1,2和那个进程的0,1,2不是一回事。

某年某月的某一天,人们发现,一个进程其实想访问另外一个进程的fd。当然,这只是目的不是手段。比如进程A有2个fd指向2片内存,如果进程B可以拿到这2个fd,其实就可以透过这2个fd访问到这2片内存。这个fd某种意义上充当了一个中间媒介的作用。有人说,那还不简单吗,如果进程A:

fd = open();

open()如果返回100,把这个100告诉进程B不就可以了吗,进程B访问这个100就可以了。这说明你还是没搞明白fd是一个进程内部的东西,是不能跨进程的概念。你的100和我的100,不是一个东西。这些基本的东西你搞不明白,你搞别的都是白搭。

Linux提供一个特殊的方法,可以把一个进程的fd甩锅、踢皮球给另外一个进程(其实“甩锅”这个词用在这里不合适,因为“甩锅”是一种推卸,而fd的传递是一种分享)。我特码一直想把我的bug甩(分)锅(享)出去,却发现总是被人把bug甩锅过来。

那么如何甩(分)锅(享)fd呢?

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    11218

    浏览量

    222974
  • Linux
    +关注

    关注

    88

    文章

    11628

    浏览量

    218007

原文标题:宋宝华:世上最好的共享内存(Linux共享内存最透彻的一篇)上集

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Linux Swap交换空间详解:Android编译内存不足?这样扩充立竿见影

        在  Linux  系统使用过程中,你是否遇到过  “ 内存不足 ”  的报错?比如编译  Android  源码时,明明按教程操作,却因物理内存没达到  16G  要求而编译中断?这正是
    的头像 发表于 12-06 08:10 3266次阅读

    不同场景下的文件共享方案-SMB/WebDAV/FTP/ZeroNews

    四大主流文件共享方案,为企业选型提供专业参考。 SMB 简介 SMB(Server Message Block) 是种网络文件共享协议,主要用于局域网(LAN)内计算机之间的文件和打印机共享
    的头像 发表于 08-28 12:04 687次阅读
    不同场景下的文件<b class='flag-5'>共享</b>方案-SMB/WebDAV/FTP/ZeroNews

    RTOS怎么实现共享内存

    K230的RTOS支持POSIX标准的共享内存吗 我尝试使用却失败 还是说需要源码部分配置的开启才可以使用 求教大佬
    发表于 08-04 08:06

    恒讯科技分析:Ubuntu云服务器数据共享高效方案

    ,帮助您根据实际需求选择最适合的解决方案。 、NFS(Network File System)共享方案 NFS是Linux系统中最常用的文件共享协议之
    的头像 发表于 07-09 21:40 1199次阅读

    RFID标签在共享经济的应用

    二、RFID标签在共享经济中的优势1.高效率:RFID可以快速批量读取信息,大幅缩短操作时间,提高管理效率。2.准确性:RFID减少了人工操作的错误率,提高了共享资源管理的准确性和可靠性。3.实时性
    的头像 发表于 07-07 15:22 368次阅读
    RFID标签在<b class='flag-5'>共享</b>经济的应用

    高性能缓存设计:如何解决缓存伪共享问题

    在多核高并发场景下, 缓存伪共享(False Sharing) 是导致性能骤降的“隐形杀手”。当不同线程频繁修改同缓存行(Cache Line)中的独立变量时,CPU缓存致性协议会强制同步整个
    的头像 发表于 07-01 15:01 503次阅读
    高性能缓存设计:如何解决缓存伪<b class='flag-5'>共享</b>问题

    黑芝麻智能芯多域零拷贝共享内存技术:破解车载大数据传输效能困局

    通过 零拷贝共享内存技术 ,黑芝麻智能解决车载多域间大数据传输的延迟与资源消耗问题。核心技术包括 全局内存管理单元 和 dmabuf机制优化 ,显著降低CPU负载与DDR带宽占用,推动汽车向
    发表于 06-23 17:53 1661次阅读
    黑芝麻智能<b class='flag-5'>一</b>芯多域零拷贝<b class='flag-5'>共享</b><b class='flag-5'>内存</b>技术:破解车载大数据传输效能困局

    HarmonyOS优化应用内存占用问题性能优化

    ,包括数字、字符串等。共享对象传输指SharedArrayBuffer支持在多线程之间传递,传递之后的SharedArrayBuffer对象和原始的SharedArrayBuffer对象指向同内存
    发表于 05-21 11:27

    golang内存分配

    作者:钱文 Go 的分配采用了类似 tcmalloc 的结构.特点: 使用小块小块的连续内存页, 进行分配某个范围大小的内存需求. 比如某个连续 8KB 专门用于分配 17-24
    的头像 发表于 03-31 15:00 385次阅读
    golang<b class='flag-5'>内存</b>分配

    无法使用API实现NPU与OpenVINO™的内存共享怎么办?

    无法使用 远程张量 API 实现 NPU 与OpenVINO™的内存共享
    发表于 03-06 07:11

    hyper-v共享,Hyper-V 共享:Hyper-V的资源共享设置

    的解决方案。今天就为大家介绍Hyper-V共享:Hyper-V的资源共享设置。    在Hyper-V虚拟化环境中,资源共享是实现高效管理和灵活部署的关键功能之。Hyper-V提供了
    的头像 发表于 02-07 10:26 1853次阅读
    hyper-v<b class='flag-5'>共享</b>,Hyper-V <b class='flag-5'>共享</b>:Hyper-V的资源<b class='flag-5'>共享</b>设置

    hyper-v共享,hyper-v共享:实现主机与虚拟机之间高效文件共享的最佳实践

    在日常工作中,我们常常需要处理大量的文件和数据,这些重复性任务不仅耗时耗力,还容易因疲劳而导致错误。幸运的是,批量管理工具的出现为这问题提供了高效的解决方案。今天就为大家介绍hyper-v共享
    的头像 发表于 01-24 14:23 2402次阅读
    hyper-v<b class='flag-5'>共享</b>,hyper-v<b class='flag-5'>共享</b>:实现主机与虚拟机之间高效文件<b class='flag-5'>共享</b>的最佳实践

    hyper 内存,Hyper内存:如何监控与优化hyper-v虚拟机的内存使用

    在日常工作中,我们常常需要处理大量的文件和数据,这些重复性任务不仅耗时耗力,还容易因疲劳而导致错误。幸运的是,批量管理工具的出现为这问题提供了高效的解决方案。今天就为大家介绍Hyper内存
    的头像 发表于 01-24 14:15 1685次阅读
    hyper <b class='flag-5'>内存</b>,Hyper<b class='flag-5'>内存</b>:如何监控与优化hyper-v虚拟机的<b class='flag-5'>内存</b>使用

    新加坡共享主机怎么设置ip

    在新加坡设置共享主机的IP地址,通常涉及多个步骤,包括评估需求、选择服务商、配置网络等。以下是个详细的设置指南,主机推荐小编为您整理发布新加坡共享主机怎么设置ip。
    的头像 发表于 01-24 11:47 744次阅读

    Linux服务器卡顿救星之招释放Cache内存

    在程序运行结束后不会自动释放。这可能会导致程序频繁读写文件后可用物理内存变得很少,必要时(比如内存确实不够用),需要主动释放缓存内存。 注意:般情况下,是不推荐主动释放缓存
    的头像 发表于 01-16 10:04 2165次阅读