当前位置: 首页 > news >正文

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(两次拷贝)总结(六十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…...

【多线程 - 01、概述】

进程 几乎所有的操作系统都支持进程概念&#xff0c;进程是处于运行过程中的程序&#xff0c;进程是操作系统中进行资源分配的基本单位。 三个基本特征 独立性&#xff1a;指进程实体是一个能独立运行、独立获得资源和独立接受调度的基本单位。而对于未建立任何进程的程序&…...

SQL SELECT INTO 语句

SQL SELECT INTO 语句 使用 SQL&#xff0c;您可以将信息从一个表中复制到另一个表中。 SELECT INTO 语句从一个表中复制数据&#xff0c;然后将数据插入到另一个新表中。 SQL SELECT INTO 语法 我们可以把所有的列都复制到新表中&#xff1a; SELECT * INTO newtable [IN ex…...

【刷题】(AtCoder Beginner Contest 328) C、D 补题

前言 第一次打 a了两道 C、D都是TLE 看了其他人的题解之后 有一些想法 所以发一篇博客 C 题干 题目链接 我的思路及做题过程 我的思路是 输入left、right 再在这个区间内计算字母相同的对数 代码是&#xff1a; #include<iostream> #include<cmath> #includ…...

NI USRP软件无线设备的特点

NI USRP软件无线设备 NI的USRP(Universal Software Radio Peripheral)设备是RF应用中使用的软件无线(SDR)。NI的USRP收发器可以在多个频段发送和接收RF信号&#xff0c;因此可用于通信工程教育和研究。通过与LabVIEW开发环境相结合&#xff0c;USRP可以实现使用无线信号验证无…...

大数据毕业设计选题推荐-污水处理大数据平台-Hadoop-Spark-Hive

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…...

最新获取支付宝cardIndex参数图文教程

本章教程主要介绍如何获取支付宝的cardIndex参数。 目录 一、登录到支付宝官网 二、在历史记录中,找到对应用户 一、登录到支付宝官网...

Linux学习第二枪(yum,vim,g++/gcc,makefile的使用)

前言&#xff1a;在我的上一篇Linux博客我已经讲了基础指令和权限&#xff0c;现在我们来学习如何在Linux上运行和执行代码 目录 一&#xff0c;yum 二&#xff0c;vim 1&#xff09;命令行模式 2&#xff09;插入模式 3&#xff09;底行模式 三&#xff0c;gcc/g 四&a…...

自然语言处理(一):RNN

「循环神经网络」&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一个非常经典的面向序列的模型&#xff0c;可以对自然语言句子或是其他时序信号进行建模。进一步讲&#xff0c;它只有一个物理RNN单元&#xff0c;但是这个RNN单元可以按照时间步骤进行展开…...

超全总结!大模型算法面试指南(含答案)

大家好&#xff0c;从 2019 年的谷歌 T5 到 OpenAI GPT 系列&#xff0c;参数量爆炸的大模型不断涌现。可以说&#xff0c;LLMs 的研究在学界和业界都得到了很大的推进&#xff0c;尤其去年 11 月底对话大模型 ChatGPT 的出现更是引起了社会各界的广泛关注。 近些年&#xff0…...

前端使用C-lodop 实现循环套打小案例

目录 前言引入js文件小案例 前言 lodop是一个很优秀打印插件&#xff0c;具体的大家可以官网了解&#xff0c;先在官网下载插件&#xff0c;安装在本地&#xff0c;并启动&#xff0c;点击官网下载 引入js文件 //本JS是加载Lodop插件或Web打印服务CLodop/Lodop7的综合示例&a…...

基于SpringBoot+Vue+mysql卓越导师双选系统设计与实现

博主介绍&#xff1a;✌Csdn特邀作者、博客专家、博客云专家、B站程序阿龙带小白做毕设系列&#xff0c;项目讲解、B站粉丝排行榜前列、专注于Java技术领域和毕业项目实战✌ 系统说明简介&#xff1a; 如今的信息时代&#xff0c;对信息的共享性&#xff0c;信息的流通性有着较…...

Windows 11系统cmd终端美化、Vscode终端美化

win11美化cmd终端和vscode的终端 1. 修改终端背景2. oh-my-posh2.1 安装oh-my-posh2.2 安装Clink2.3 Clink配置oh-my-posh2.4 下载和配置Nerd字体2.5 修改美化主题 3. vscode终端美化 电脑默认的终端没有语法高亮这些&#xff0c;运行命令和代码输出字体一样&#xff0c;有时会…...

[游戏中的图形学实时渲染技术] Part1 实时阴影技术

原理篇&#xff1a; 常见的渲染方程如下&#xff1a; 在不考虑自发光项与考虑阴影对于着色结果的影响之后可以将方程变化为如下形式&#xff1a; 如果射线在到达光源前击中了其他物体时&#xff0c;就认为这条来自光源的光线对着色点没有贡献。 利用上述渲染方程进行正确的着…...

NtripShare Mos地铁自动化监测终端盒子硬件设计

自动化监测产品到目前为止做了接近一年&#xff0c;在软件层面上&#xff0c;控制终端软件、平台软件、网平差算法都已解决&#xff0c;硬件盒子始终是心里过不去的坎&#xff0c;最终还是没有耐住性子自己做了一把。 选型如下&#xff1a; 1、主板:瑞芯微RK3568主板。 2、外…...

第 117 场 LeetCode 双周赛题解

A 给小朋友们分糖果 I 动态规划&#xff1a;设 p [ k ] [ i ] p[k][i] p[k][i] 为将 i i i 个糖果分给 k k k 个小朋友的方案数&#xff0c;先求 p [ 2 ] [ i ] p[2][i] p[2][i] &#xff0c;再求 p [ 3 ] [ n ] p[3][n] p[3][n] class Solution { public:using ll long …...

OpenCV C++ 图像处理实战 ——《多二维码识别》

OpenCV C++ 图像处理实战 ——《多二维码识别》 一、结果演示二、zxing库配置2.1下载编译三、多二维码识别3.1 Method one3.1.1 源码3.2 Method two3.2.1 源码四、源码测试图像下载总结一、结果演示 </...

经典算法(查找与排序)

查找 顺序查找 顺序查找&#xff08;Linear Search&#xff09;是一种在有序数组中查找目标元素的基本算法。它的时间复杂度为 O(n)&#xff0c;适用于查找少量数据。顺序查找的基本思想是从数组的第一个元素开始&#xff0c;逐个与待查找的元素进行比较&#xff0c;直到找到…...

微软和Red Hat合体:帮助企业更方便部署容器

早在2015年&#xff0c;微软就已经和Red Hat达成合作共同为企业市场开发基于云端的解决方案。时隔两年双方在企业市场的多个方面开展更紧密的合作&#xff0c;今天两家公司再次宣布帮助企业更方便地部署容器。 双方所开展的合作包括在微软Azure上部署Red Hat OpenShift&#xf…...

ZYNQ_project:IP_ram_pll_test

例化MMCM ip核&#xff0c;产生100Mhz&#xff0c;100Mhz并相位偏移180&#xff0c;50Mhz&#xff0c;25Mhz的时钟信号。 例化单口ram&#xff0c;并编写读写控制器&#xff0c;实现32个数据的写入与读出。 模块框图&#xff1a; 代码&#xff1a; module ip_top(input …...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...