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

本文主要是介绍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 accessstd::string message = "Hello, IPC using semaphores!";// Perform operations on the shared resourceif (semop(semid, &release, 1) == -1) {std::cerr << "Failed to release semaphore" << std::endl;return 1;}return 0;
}

这篇关于Linux之IPC通信共享内存与消息队列、管道、信号量、socket内存拷贝实例总结(六十二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/381407

相关文章

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

SpringKafka消息发布之KafkaTemplate与事务支持功能

《SpringKafka消息发布之KafkaTemplate与事务支持功能》通过本文介绍的基本用法、序列化选项、事务支持、错误处理和性能优化技术,开发者可以构建高效可靠的Kafka消息发布系统,事务支... 目录引言一、KafkaTemplate基础二、消息序列化三、事务支持机制四、错误处理与重试五、性能优

SpringIntegration消息路由之Router的条件路由与过滤功能

《SpringIntegration消息路由之Router的条件路由与过滤功能》本文详细介绍了Router的基础概念、条件路由实现、基于消息头的路由、动态路由与路由表、消息过滤与选择性路由以及错误处理... 目录引言一、Router基础概念二、条件路由实现三、基于消息头的路由四、动态路由与路由表五、消息过滤

Linux samba共享慢的原因及解决方案

《Linuxsamba共享慢的原因及解决方案》:本文主要介绍Linuxsamba共享慢的原因及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux samba共享慢原因及解决问题表现原因解决办法总结Linandroidux samba共享慢原因及解决

springboot security验证码的登录实例

《springbootsecurity验证码的登录实例》:本文主要介绍springbootsecurity验证码的登录实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录前言代码示例引入依赖定义验证码生成器定义获取验证码及认证接口测试获取验证码登录总结前言在spring

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

tomcat多实例部署的项目实践

《tomcat多实例部署的项目实践》Tomcat多实例是指在一台设备上运行多个Tomcat服务,这些Tomcat相互独立,本文主要介绍了tomcat多实例部署的项目实践,具有一定的参考价值,感兴趣的可... 目录1.创建项目目录,测试文China编程件2js.创建实例的安装目录3.准备实例的配置文件4.编辑实例的