Linux之IPC通信共享内存(一次拷贝)与消息队列、管道、信号量、socket(两次拷贝)总结(六十二)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的:理解IPC通信消息队列、管道、socket两次内存拷贝与共享内存一次内存拷贝。

2.IPC通信消息队列、管道、socket、共享内存介绍

  • 在Linux和Android中,进程间通信(IPC)的方式有很多种,包括管道(Pipe)、消息队列(Message Queue)、共享内存(Shared Memory)、信号量(Semaphore)、套接字(Socket)等。其中,管道、消息队列、套接字都需要进行两次内存拷贝,而共享内存只需要一次内存拷贝。

1. 两次内存拷贝的IPC方式:

  • 管道(Pipe): 当一个进程向管道中写入数据时,数据首先会被拷贝到内核缓冲区,然后当另一个进程从管道中读取数据时,数据会从内核缓冲区拷贝到该进程的内存空间。这就是两次内存拷贝。

  • 消息队列(Message Queue): 消息队列的工作方式与管道类似,数据在发送和接收时都需要经过内核缓冲区,因此也需要两次内存拷贝。

  • 套接字(Socket): 套接字在发送和接收数据时,数据也需要经过内核缓冥区,因此也需要两次内存拷贝。

2. 一次内存拷贝的IPC方式:

  • 共享内存(Shared Memory): 共享内存是最快的IPC方式,因为进程是直接对内存进行操作,数据不需要在进程和内核之间进行拷贝。但是,由于多个进程可以同时操作同一块内存,因此需要使用信号量等同步机制来防止数据的不一致。

3.总结

  • 一次内存拷贝:
    一次内存拷贝是指数据在用户空间和内核空间之间只进行了一次拷贝。在Linux和Android中,使用共享内存(shared memory)实现IPC通信是一种一次内存拷贝的方式。共享内存允许多个进程共享同一块物理内存,因此数据被写入内核空间后,其他进程可以直接在内存中读取数据,避免了多次拷贝的开销。

  • 两次内存拷贝:
    两次内存拷贝指数据在用户空间和内核空间之间进行了两次拷贝。在Linux和Android中,使用Socket、管道(pipe)和消息队列(message queue)进行IPC通信会涉及两次内存拷贝。

3.代码实例

1.共享内存进行一次内存拷贝

#include <iostream>
#include <sys/shm.h>
#include <cstring>

int main() {
    key_t key = ftok("/tmp", 'S');
    int shmid = shmget(key, 1024, 0666 | IPC_CREAT);
    char *data = (char*)shmat(shmid, nullptr, 0);

    std::string message = "Hello, IPC using shared memory!";
    std::memcpy(data, message.c_str(), message.size());

    shmdt(data);
    shmctl(shmid, IPC_RMID, nullptr);
    return 0;
}

2.Socket进行两次内存拷贝

// 服务器端
#include <iostream>
#include <sys/socket.h>
#include <cstring>

int main() {
    int server_sock = socket(AF_INET, SOCK_STREAM, 0);
    // 绑定和监听

    int client_sock = accept(server_sock, nullptr, nullptr);

    std::string message = "Hello, IPC using sockets!";
    send(client_sock, message.c_str(), message.size(), 0);

    close(client_sock);
    close(server_sock);

    return 0;
}

// 客户端
#include <iostream>
#include <sys/socket.h>
#include <cstring>

int main() {
    int client_sock = socket(AF_INET, SOCK_STREAM, 0);
    // 连接服务器

    char buffer[1024];
    recv(client_sock, buffer, sizeof(buffer), 0);
    std::cout << "Message received from server: " << buffer << std::endl;

    close(client_sock);

    return 0;
}

3.管道进行两次内存拷贝

#include <iostream>
#include <unistd.h>
#include <cstring>

int main() {
    int pipe_fds[2];

    if (pipe(pipe_fds) == -1) {
        std::cerr << "Failed to create pipe" << std::endl;
        return 1;
    }

    const char* message = "Hello, IPC using pipes!";
    const size_t len = strlen(message);

    if (write(pipe_fds[1], message, len) != static_cast<ssize_t>(len)) {
        std::cerr << "Failed to write to pipe" << std::endl;
        return 1;
    }

    char buffer[64];
    ssize_t bytes_read = read(pipe_fds[0], buffer, sizeof(buffer));
    if (bytes_read == -1) {
        std::cerr << "Failed to read from pipe" << std::endl;
        return 1;
    }

    std::cout << "Message read from pipe: " << std::string(buffer, bytes_read) << std::endl;

    close(pipe_fds[0]);
    close(pipe_fds[1]);

    return 0;
}

4.消息队列进行两次内存拷贝

#include <iostream>
#include <cstring>
#include <sys/msg.h>

struct Message {
    long type;
    char text[100];
};

int main() {
    key_t key = ftok("/tmp", 'Q');
    int msgid = msgget(key, 0666 | IPC_CREAT);

    Message message;
    message.type = 1;
    std::strcpy(message.text, "Hello, IPC using message queues!");

    msgsnd(msgid, &message, sizeof(message.text), 0);

    msgrcv(msgid, &message, sizeof(message.text), 1, 0);
    std::cout << "Message received from message queue: " << message.text << std::endl;

    msgctl(msgid, IPC_RMID, nullptr);

    return 0;
}

5.信号量进行两次内存拷贝

#include <iostream>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <unistd.h>
#include <cstring>

int main() {
    key_t key = ftok("/tmp", 'S');
    int semid = semget(key, 1, IPC_CREAT | 0666);
    if (semid == -1) {
        std::cerr << "Failed to create semaphore" << std::endl;
        return 1;
    }

    sembuf acquire = {0, -1, SEM_UNDO};
    sembuf release = {0, 1, SEM_UNDO};

    if (semop(semid, &acquire, 1) == -1) {
        std::cerr << "Failed to acquire semaphore" << std::endl;
        return 1;
    }

    // Critical section - perform operations that require exclusive access

    std::string message = "Hello, IPC using semaphores!";
    // Perform operations on the shared resource

    if (semop(semid, &release, 1) == -1) {
        std::cerr << "Failed to release semaphore" << std::endl;
        return 1;
    }

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/128017.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

工业废水处理设备公司如何挑选

在选择工业废水处理设备公司时&#xff0c;需要从以下几个方面进行考虑&#xff1a; 公司实力和资质&#xff1a;选择具有相关资质和经验的废水处理设备公司&#xff0c;能够提供高质量的设备和服务。可以通过查询公司的官方网站、客户评价等信息来了解公司的实力和资质。设备…

大厂面试题-数据库连接池有什么用?它有哪些关键参数?

从这几个方面来回答&#xff1a; 首先&#xff0c;数据库连接池是一种池化技术&#xff0c;池化技术的核心思想是实现资源的复用&#xff0c;避免资源重复创建销毁的开销。 而在数据库的应用场景里面&#xff0c;应用程序每次向数据库发起CRUD操作的时候&#xff0c;都需要创…

AI生成技术威胁版权保护,水印技术和法律完善是关键/安圭拉小岛以.ai域名注册赚得3000万美元 |魔法半周报

我有魔法✨为你劈开信息大海❗ 高效获取AIGC的热门事件&#x1f525;&#xff0c;更新AIGC的最新动态&#xff0c;生成相应的魔法简报&#xff0c;节省阅读时间&#x1f47b; &#x1f525;资讯预览 AI生成技术威胁版权保护&#xff0c;水印技术和法律完善是关键 Sam Altman对…

【Git】Git图形化工具SSH协议IDEA集成Git的使用讲解

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《Git》。&#x1f3af;&#x1f3af; &#x1f449…

企业年会/年终活动如何邀请媒体记者报道?

​媒体邀约是企业或组织进行宣传的重要手段之一。通过邀请媒体参加活动&#xff0c;可以增加活动的曝光度和知名度&#xff0c;吸引更多的关注和参与。同时&#xff0c;媒体报道还可以提高企业或组织的权威性和可信度&#xff0c;从而让公众更容易接受其传达的信息。 企业年会或…

实时疫情地图及全国监测动态大屏可视化【可视化项目案例-02】

🎉🎊🎉 你的技术旅程将在这里启航! 🚀🚀 本文选自专栏:可视化技术专栏100例 可视化技术专栏100例,包括但不限于大屏可视化、图表可视化等等。订阅专栏用户在文章底部可下载对应案例源码以供大家深入的学习研究。 🎓 每一个案例都会提供完整代码和详细的讲解,不…

索引是什么?如何创建?哪些情况下需要使用?

在数据库中&#xff0c;索引是一种用于提高查询速度的数据结构。它可以帮助我们快速地找到需要的数据&#xff0c;而不必扫描整个数据库。如果你是一名业务人员&#xff0c;你可能会问&#xff1a;“为什么我们需要使用索引&#xff1f;” 一、什么是索引&#xff1f; 索引是一…

家乡特色饮食体验系统的设计与实现-计算机毕设 附源码 27533

家乡特色饮食体验系统的设计与实现 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对家乡特色…

日常交流没有障碍,听力就一定正常吗?

你卖灯笼啊&#xff1f; 对啊对啊&#xff0c;我耳朵聋&#xff01; 你这灯笼多少钱呀&#xff1f; 我耳朵聋了好几年啦&#xff01; 这是个笑话 当然也可以从中看出 听力障碍对一个人日常生活的影响 日常交流没障碍 就是听力正常了吗&#xff1f; 首先我们要了解&#xf…

Xcode 最好用的 11 个快捷键

今天来分享一下我觉得很好用的 Xcode 12 个快捷键 1. Command Shift O 快速打开&#xff0c;可让你快速导航到项目中的任何文件、函数、变量 2. Command Shift J 快速定位到当前代码所在的文件夹位置&#xff0c;并切换到项目导航器中显示 3. Command Shift Y 快速…

探索双十一:从技术角度剖析电商狂欢节

每年的11月11日&#xff0c;全球最大的在线购物狂欢节“双十一”在中国掀起了一场规模空前的消费风暴。以阿里巴巴为代表的电商平台和众多品牌商家&#xff0c;不仅为消费者提供了数以亿计的优惠商品&#xff0c;同时也将这一活动打造成了一个科技与商业完美结合的标志事件。本…

2023 年最佳 Android 数据恢复软件工具

Android 数据恢复软件将使您能够从 Android 智能手机中检索所有已删除的文件。您需要此类软件的原因是由于不同情况下会丢失数据。例如&#xff0c;病毒攻击会导致数据损坏和文件丢失。 Android 数据恢复软件工具清单 以下是十个最佳 Android 数据恢复软件工具&#xff0c;用于…

D136-002-005带D138-002-002加密狗

D136-002-005带D138-002-002加密狗 德国自动化公司的ROTARNOCK 80和ROTARNOCK 100电子凸轮控制器现在也可以通过PROFINET接口使用。该设备可通过易于使用的PC用户界面、PROFINET控件或通过Deutschmann TERM系列的高性能终端进行操作。 所有型号都可以非常容易地连接到西门子…

FFMPEG库实现mp4/flv文件(H264+AAC)的封装与分离

ffmepeg 4.4&#xff08;亲测可用&#xff09; 一、使用FFMPEG库封装264视频和acc音频数据到 mp4/flv 文件中 封装流程 1.使用avformat_open_input分别打开视频和音频文件&#xff0c;初始化其AVFormatContext&#xff0c;使用avformat_find_stream_info获取编码器基本信息 2.使…

Spring Cloud Config、Apollo、Nacos和Archaius对比

一、适应场景 Spring Cloud Config、Apollo、Nacos、Archaius这四个配置中心在功能和使用场景上有所差异。 1.Spring Cloud Config Spring Cloud Config是Spring Cloud官方提供的分布式系统的外部配置中心。它提供了服务器和客户端支持&#xff0c;可以集中管理不同环境、不同集…

【性能测试】Linux下Docker安装与docker-compose管理容器(超细整理)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、Linux下Docker…

conda修改虚拟环境名称

conda 修改虚拟环境名称 conda 不能直接更改名称&#xff0c;但是可以通过克隆环境解决 新建环境&#xff08;克隆旧环境&#xff09; conda create --name 新环境名 --clone 旧环境名 删除原环境 conda remove --name 旧环境名 --all 查看现有环境 conda env list conda i…

commons-io

概述 commons-io是apache开源基金组织提供的一组有关IO操作的类库&#xff0c;可以提高IO功能开发的效率。 commons-io工具包提供了很多有关io操作的类。有两个主要的类FileUtils, IOUtils。 FileUtils主要有如下方法: 使用commons-io简化io流读写 在项目中创建一个文件夹&…

银河麒麟操作系统安装_V4/V10系统详细使用教程

银河麒麟桌面操作系统V10是一款简单易用、稳定高效、安全创新的新一代图形化桌面操作系统产品。现已适配国产主流软硬件产品&#xff0c;同源支持飞腾、鲲鹏、海思麒麟、龙芯、申威、海光、兆芯等国产CPU和Intel、AMD平台&#xff0c;通过功耗管理、内核锁及页拷贝、网络、VFS、…

筹码穿透率指标选股公式,衡量筹码抛压

在前面的文章中&#xff0c;介绍了博弈K线&#xff0c;它是根据筹码分布的原理结合普通K线的方法绘制出来的。当博弈K线的实体部分比较长的时候&#xff0c;说明当天穿越筹码密集区&#xff0c;有大量的筹码解套。通过引入换手率&#xff0c;可以衡量套牢盘的抛压程度。如果穿越…