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/126162.html

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

相关文章

射频功率放大器应用中GaN HEMT的表面电势模型

标题&#xff1a;A surface-potential based model for GaN HEMTs in RF power amplifier applications 来源&#xff1a;IEEE IEDM 2010 本文中的任何第一人称都为论文的直译 摘要&#xff1a;我们提出了第一个基于表面电位的射频GaN HEMTs紧凑模型&#xff0c;并将我们的工…

ChatGPT如何管理对话历史?

问题 由于现在开始大量使用ChatGPT对话功能&#xff0c;认识到他在提供启发方面具有一定价值。比如昨天我问他关于一个微习惯的想法&#xff0c;回答的内容还是很实在&#xff0c;而且能够通过他的表达理解自己的问题涉及到的领域是什么。 此外&#xff0c;ChatGPT能够总结对话…

96 前缀树Trie

前缀树 题解1 STL题解2 参考官方 Trie&#xff08;发音类似 “try”&#xff09;或者说 前缀树 是一种树形数据结构&#xff0c;用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景&#xff0c;例如自动补完和拼写检查。 请你实现 Trie 类&#xff1a; …

强化IP地址管理措施:确保网络安全与高效性

IP地址管理是网络安全和性能管理的关键组成部分。有效的IP地址管理可以帮助企业确保网络的可用性、安全性和高效性。本文将介绍一些强化IP地址管理的关键措施&#xff0c;以帮助企业提高其网络的安全性和效率。 1. IP地址规划 良好的IP地址规划是强化IP地址管理的基础。它涉及…

中断 NVIC的概念和原理

1.什么是中断 中断&#xff1a; 由于中断源的触发&#xff0c;常规程序被打断&#xff0c; CPU转 而运行中断响应函数&#xff0c;而后又回到常规程序的执行&#xff0c; 这一过程叫做中断。 中断优先级的概念 中断的意义和作用 中断处理的过程和术语 STM32 GPIO外部中断简…

宠物商店系统《宠物之家》,巨完善

源码下载地址 支持&#xff1a;远程部署/安装/调试、讲解、二次开发/修改/定制 系统分为用户端和管理员端。 截图中有些图片加载失败&#xff0c;是因为没有上传图片&#xff0c;登录管理员账号上传图片后&#xff0c;图片显示会变成正常。 web的宠物商城系统《宠物之家》。系…

mysql千万数据快速插入-实战

文章目录 前言环境一、配置二、效果总结 前言 数据量太大了&#xff0c;每天半夜要同步很大数据到 mysql 数据库&#xff0c;其中一张表就上2千万&#xff0c;总计上亿条数据。同步任务每天0点之后开始任务&#xff08;因为到0之后才能统计前一天数据&#xff09;&#xff0c;…

Antv/G2 图表背景实线改为虚线

坐标轴 - Axis 文档 绘图属性 - ShapeAttrs 文档 图表背景实线改为虚线代码示例&#xff1a; chart.axis("value", {grid: {// 背景网格刻度线样式line: {style: {lineWidth: 0.5,lineDash: [5, 2], //虚线},},}, });未设置前页面效果&#xff1a; 添加代码配置&…

AutoGen 智能应用开发(一)|AutoGen 基础

点击蓝字 关注我们 编辑&#xff1a;Alan Wang 排版&#xff1a;Rani Sun 微软 Reactor 为帮助广开发者&#xff0c;技术爱好者&#xff0c;更好的学习 .NET Core, C#, Python&#xff0c;数据科学&#xff0c;机器学习&#xff0c;AI&#xff0c;区块链, IoT 等技术&#xff0…

智慧社区大屏:连接社区生活的数字桥梁

随着科技的不断发展&#xff0c;智慧社区已经不再只是未来的概念&#xff0c;它已经在我们的眼前悄然崭露头角。智慧社区是一种基于数字技术的社区管理和生活方式&#xff0c;旨在提高社区的安全性、便利性和生活质量。而在这个数字化的社区中&#xff0c;智慧社区大屏起到了连…

基于Qt窗口文件新建_编辑_打开_保存_另存_剪切和复制和粘贴项目(文件操作直接套源码)

# .pro文件 QT += widgetsrequires(qtConfig(filedialog))​HEADERS = mainwindow.hSOURCES = main.cpp \ mainwindow.cppRESOURCES = sdi.qrc​# installtarget.path = $$[QT_INSTALL_EXAMPLES]/widgets/mainwindows/sdiINSTALLS += target​…

【C++数据结构】顺序存储结构的抽象实现

文章目录 前言一、目标二、SeqList实现要点三、SeqList函数实现3.1 get函数3.2 set函数3.3 insert函数带2个参数的insert带一个参数的insert 3.4 remove函数3.5 clear函数3.6 下标运算符重载函数无const版本const版本 3.7 length函数 总结 前言 当谈到C数据结构时&#xff0c;…

商人宝:新版收银系统比传统的收银机有哪些优势

新版收银系统凭借安装迅速、使用便捷、升级省心等特点&#xff0c;正逐步替换掉传统的安装下载的C/S架构的收银系统。今天&#xff0c;小编为大家分享新版收银系统对比传统收银机的三大优势。欢迎大家点赞关注&#xff0c;以及收藏本文章&#xff0c;以便后续多了解。 一是网页…

Direct3D粒子系统

粒子和点精灵 粒子(是种微小的物体,在数学上通常用点来表示其模型。所以显示粒子时,使用点图元(由 D3 DPRIMITIVETYPE类型的D3 DPT POINTLIST枚举常量表示)是一个很好的选择。但是光栅化时,点图元将被映射为一个单个像素。这样就无法为我们提供很大的灵活性,因为实际应用…

centos7下安装主从仲裁三台结构的MongoDB 7.0.4

安装手册英文版在这里 https://www.mongodb.com/docs/v7.0/tutorial/install-mongodb-on-red-hat/ 我的安装过程 1&#xff09;基础安装 1、创建 /etc/yum.repos.d/mongodb-org-7.0.repo文件 下面的代码复制到这个文件中&#xff0c;保存 [mongodb-org-7.0] nameMongoDB Re…

如何像专家一样高效使用搜索引擎?适用于百度Baidu、谷歌Google

你几乎可以在互联网上搜索到任何内容,而Google是大多数人选择搜索信息的主要途径之一。 尽管频繁地使用Google,但是大部分互联网用户都不知道如何快速和高效地使用Google搜索。 可以说使用Google是一门艺术。 想要获得正确的答案,你需要提出正确的问题。想要快速地获得正…

黑豹程序员-SpringBoot中整合knife4j接口文档

1、Knife介绍 黑豹程序员-架构师学习路线图-百科&#xff1a;Knife4j API接口文档管理 2、坐标 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>2.0.7</version&…

原神游戏干货分享:探索璃月的宝箱秘密,提高游戏资源获取效率!

《原神》是一款备受玩家喜爱的开放世界冒险游戏&#xff0c;而在游戏中获取资源是提升角色实力的重要途径。在这篇实用干货分享中&#xff0c;我们将介绍一些探索璃月地区的宝箱秘密&#xff0c;帮助你提高游戏资源获取的效率。 首先&#xff0c;璃月地区的宝箱分为普通宝箱和精…

潼南柠檬产业发展大会举行 这三个场景“柠”聚了人气

华龙网讯&#xff08;首席记者 羊华&#xff09;今&#xff08;6&#xff09;日下午&#xff0c;2023中国潼南柠檬产业发展大会正式举行。潼南区准备了“大礼包”&#xff0c;既有专业论坛峰会&#xff0c;也首发了“柠檬产业大脑”&#xff0c;还进行了招商引资集中签约&#…

机组 CPU

控制器&#xff1a;协调并控制计算机各部件执行程序的指令序列&#xff0c;其基本功能是取指令、分析指令和执行指令 功能 CPU 必须具有控制程序的顺序执行&#xff08;指令控制&#xff09;、产生完成每条指令所需的控制命令&#xff08;操作控制&#xff09;、对各种操作加…