《共享内存》Linux进程间通信入门

Linux内核入门(十)——进程间通信:共享内存 Linux内核入门(十)——进程间通信:共享内存前言什么是共享内存创建一块共享内存代码测试 前言 上回书说到信号,七七八八的东西比较多,相比之下,共享内存就没那么多弯弯绕绕了,共享内存的使用思路和前面讲的管道通信比较像,我们来看看 什么是共享内存 顾名思义:共享内存本质是一段内存,它存在于内核空间,由用户创建和销毁,不同进程可以共同访问同一段共享内存。 这里就有个问题,共享内存谁都可以来随时读写,万一同时有两个进程同时在读写同一段共享内存咋办?这不得打起来?共享内存是不提供同步机制的,所以作为程序员需要编写 阅读详情

个人微信公众号: fensnote

简述

共享内存是Linux系统进程间通信常用的方式,通常用于数据量较大的情况,如果只是用于不同的进程间消息通知,那不如用消息队列或者socket。之前做的项目中,使用共享内存的其实只有一种情况:视频数据的共享。设备类似于DVR,视频采集编码在一个独立的程序中,另一个程序负责协议通信。

共享内存要想好用,共享的那段内存,需要用数据结构和队列组织起来,加上读写索引和数据有效标志(已读和未读、可读)。下面的这个示例代码是我初学时的,适合入门和了解使用流程。

代码

写端代码
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>

#define N 1024

typedef struct
{
    pid_t pid;
    char text[N];
}SHMBUF;

void handler(int signo) {printf("signo=%d\n", signo);}

int main()
{
	int shmid;
    SHMBUF *shmadd;
    key_t key;
    pid_t peerpid;

    if ((key = ftok(".", 'a')) == -1)
    {
        perror("ftok");
        exit(-1);
    }

    signal(SIGUSR1, handler);

	if ((shmid = shmget(key, sizeof(SHMBUF), 0666 | IPC_CREAT | IPC_EXCL)) == -1)
	{
        if (errno == EEXIST)
        {
            shmid = shmget(key, sizeof(SHMBUF), 0666);
	        if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
        	{
	         	perror("shmat");
		        exit(-1);
        	}
            peerpid = shmadd->pid;
            shmadd->pid = getpid();
            kill(peerpid, SIGUSR1);
        }
        else
        {
    	    perror("shmget");
	    	exit(-1);
        }
	}
    else    //first process
    {
	    if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
    	{
	    	perror("shmat");
		    exit(-1);
    	}
        shmadd->pid = getpid();
        //sprintf(shmadd, "%d", getpid());
        pause();
        peerpid = shmadd->pid;
    }

    printf(">");
    while (1)
    {
        fgets(shmadd->text, N, stdin);
        shmadd->text[strlen(shmadd->text)-1] = '\0';
        kill(peerpid, SIGUSR1);
        if (strncmp(shmadd->text, "quit", 4) == 0)
        {
            sleep(1);
	        if (shmdt(shmadd) == -1)
        	{
		        perror("shmdt");
        	}
	        if (shmctl(shmid, IPC_RMID, NULL) == -1)
        	{
		        perror("RM");
        		exit(-1);
        	}

            exit(0);
        }
        pause();
        printf(">");
    }

	return 0;
}
读取端代码
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <string.h>
#include <unistd.h>

#define N 1024

typedef struct
{
    pid_t pid;
    char text[N];
}SHMBUF;

void handler(int signo) {printf("signo=%d\n", signo);}
int main()
{
	int shmid;
    SHMBUF *shmadd;
    key_t key;
    pid_t peerpid;

    if ((key = ftok(".", 'a')) == -1)
    {
        perror("ftok");
        exit(-1);
    }

    signal(SIGUSR1, handler);

	if ((shmid = shmget(key, sizeof(SHMBUF), 0666 | IPC_CREAT | IPC_EXCL)) == -1)
	{
        if (errno == EEXIST)
        {
            shmid = shmget(key, sizeof(SHMBUF), 0666);
	        if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
        	{
	         	perror("shmat");
		        exit(-1);
        	}
            peerpid = shmadd->pid;
            shmadd->pid = getpid();
            kill(peerpid, SIGUSR1);
        }
        else
        {
    	    perror("shmget");
	    	exit(-1);
        }
	}
    else    //first process
    {
	    if ((shmadd = (SHMBUF *)shmat(shmid, NULL, 0)) == (SHMBUF *)-1)
    	{
	    	perror("shmat");
		    exit(-1);
    	}
        shmadd->pid = getpid();
        pause();
        peerpid = shmadd->pid;
    }

    while (1)
    {
        pause();
        printf("read %s\n", shmadd->text);
        if (strncmp(shmadd->text, "quit", 4) == 0)
        {
	        if (shmdt(shmadd) == -1)
        	{
		        perror("shmdt");
        	}
            exit(0);
        }
       // sleep(1);
       usleep(100000);
       kill(peerpid, SIGUSR1);
    }
    exit(0);
}
编译

gcc reader.c -o reader
gcc writer.c -o writer

运行

在这里插入图片描述
代码见:https://gitee.com/fensnote/demo_code

微信公众号

在这里插入图片描述

Qt实现的TCP端口转发工具 使用Qt实现了一个Tcp端口转发的工具,实现功能具体如下: 本地启动一个服务,接收远端客户端的连接。同时也会连接另一个服务器,会将 接收到客户端的数据,转发到连接的服务器上面。 通过该工具的编码,也正好练习了一下Qt的socket编程(服务器/客户端),是个 不错的例子,欢迎大家来Emil索取源码,共同学习! Emil:wuquan-1230@163.com 立即下载

相关推荐

进程间通信(IPC):共享内存和消息队列原理详解

操作系统内的并发执行进程可以是独立的也可以是协作的: 如果一个进程不能影响其他进程或受其他进程影响,那么该进程是独立的,换句话说,不与任何其他进程共享数据的进程是独立的; 如果一个进程能影响其他进程或受其他进程所影响,那么该进程是协作的。换句话说,与其他进程共享数据的进程为协作进程。提供环境允许进程协作,具有许多理由: 信息共享:由于多个用户可能对同样的信息感兴趣(例如共享文件),所以应提供环境以允许并发访问这些信息。

C语言Log工具推荐-easylogger

文章目录日志简述EasyLogger简介编译运行附录EasyLogger说明1. 介绍1.1 主要特性1.2 插件1.3 Star & Fork2. 使用2.1 参数配置2.2 输出级别2.2.1 输出缤纷多彩的日志2.3 输出过滤2.4 输出格式2.5 输出方式2.6 Demo2.6.1 核心功能2.6.2 Flash Log(将日志保存到 Flash 中)2.6.2 File Log(将日志保存到文件中)3. 文档4. 后期5. 许可 日志简述 C/CPP的日志工具也很多,在之前的项目中用过的有

风声的专栏 3932

AutoSAR RTE调度机制揭秘:从定时器事件到Runnable执行的完整流程

本文深入解析了AutoSAR RTE(运行时环境)的核心调度机制,详细阐述了从定时器事件触发到Runnable(可运行实体)执行的完整流程。通过剖析Rte_Start()函数、OS任务与警报的交互,以及事件驱动循环,揭示了RTE如何作为幕后指挥家,高效、可靠地协调软件组件间的周期性任务执行,是打通AutoSAR应用开发的关键。

weixin_29169899的博客 226

基于Qt实现的TCP端口数据转发服务器

对于Qt,比较喜欢qt的sdk框架,我也是用于做一些工作中用到的工具软件,基于qt的sdk做起来也比较快; 一、概述 今天要说的这个tcp端口转发服务器,主要是用于将监听端口的数据转发到另外一个服务器的端口上,这个工具软件的作用有以下几点: 1.监视协议交互数据,一方面是数据内容,另一个方面是协议交互(服务端到底有没有应答数据,客户端的数据有没有发出来) 2.网络代理;客户...

风声的专栏 5066

Qt+OpenGL+Cesium三件套:打造高性能3D GIS桌面应用的5个关键点

本文深入探讨了如何利用Qt、OpenGL和Cesium数据规范构建高性能桌面级3D GIS应用。文章聚焦于五个关键点:架构选型、OpenGL渲染优化、3D Tiles数据解析与调度、内存与多线程管理,以及高级特性实现,旨在帮助开发者在C++生态中打造不依赖网络、运算能力更强的重型3D地理信息客户端。

weixin_28197941的博客 380

YOLOv11火焰识别:从环境搭建到GUI部署的完整工程实践

目标检测是计算机视觉的核心任务之一,它通过定位和分类图像中的物体,为机器赋予“看懂”世界的能力。其原理通常基于深度学习模型,如YOLO系列,通过卷积神经网络提取特征并预测边界框与类别。这项技术的价值在于将算法能力转化为实际生产力,广泛应用于安防监控、工业质检、自动驾驶等场景。在工程实践中,环境配置的稳定性与数据质量往往决定项目成败,而模型部署的易用性直接影响最终用户体验。本文以火焰识别这一具体应用为切入点,详细解析了如何利用YOLOv11完成从零到产品化的全链路流程,其中涉及Conda虚拟环境管理、PyTo

weixin_29483277的博客 234

进程间通讯共享内存的具体步骤

在两个进程间共享数据的方法,至今为止我们只说过利用管道。管道只是利用了输入输出重定向的原理,非常简单。而且只能在父子进程间使用。很多场合下这种方法是无法满足我们的要求的。那么现在,我们又有了一种新的方法——利用共享内存(shared memory)。这可以使我们在任意两个进程间传递数据,而且也是相对简单容易实现的一个方法。注意:在正常情况下,一个进程的所使用的内存区是不允许其它进程访问的。这里我们

在路上…… 1508

保姆级教程:用Cesium的Primitive API实现火箭发射全流程动画(含代码避坑)

本文详细介绍了如何使用Cesium的Primitive API实现火箭发射全流程动画,包括模型控制、关节动画和精细时序管理。通过实战代码示例和性能优化技巧,帮助开发者高效构建高复杂度航天仿真系统,显著提升三维可视化效果与运行效率。

weixin_42565652的博客 212

Linux进程间通信之《共享内存》入门

共享内存是Linux系统进程间通信常用的方式,通常用于数据量较大的情况,如果只是用于不同的进程间消息通知,那不如用消息队列或者socket。之前做的项目中,使用共享内存的其实只有一种情况:视频数据的共享。设备类似于DVR,视频采集编码在一个独立的程序中,另一个程序负责协议通信。

风声的专栏 358

APM水下机器人实战:从零搭建高精度自主航行系统

本文详细介绍了如何基于开源APM飞控及其水下分支ArduSub,从零搭建高精度自主水下航行器。核心在于集成双天线RTK模块实现厘米级定位与精确航向,并配合MAVROS与ROS构建自主控制系统。文章涵盖了硬件选型、软件配置、自主逻辑开发及水池调试的全流程实战经验,为水下机器人爱好者与研究者提供了一套完整的自主航行系统解决方案。

app77的博客 512

SAP期初库存导入 (1)

LSMW

IT养家 7191

Linux入门篇——进程间通信之共享内存

SystemV的简单介绍,共享内存的相关函数、相关命令的简单应用

qq_56101220的博客 397

Kimodo 入门教程(一)英伟达开源人形机器人动捕数据集训练运动学动作扩散模型

Kimodo是一个基于700小时商用光学动作捕捉数据集训练的运动学动作扩散模型,能够生成高质量的人体和机器人3D动作。该模型支持通过文本提示和多种约束条件(如关键帧、末端执行器位置等)进行控制,并提供数字人类和类人机器人两种模型变体。安装方式包括软件包安装和源代码安装两种,需要配置HuggingFace令牌以访问文本编码器。推荐使用GPU加速,最低需要17GB显存。项目提供命令行生成和交互式演示两种使用方式,演示程序支持时间轴编辑和实时3D可视化。模型分为商用友好版和受限版,其中SMPL-X版本需要额外申请

2506_90492529的博客 1927

linux入门:进程间通信之共享内存

Linux进程间通信(IPC)之共享内存:shmget,shmat,shmdt,shmctl

if9600的博客 422

图像紫边消除(depurple)

对图像紫边形成原因、消除方法进行了介绍。

沧海一升的博客 7565

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Linux基础入门--进程间通信--共享内存

Linux基础入门--进程间通信--共享内存1.共享内存IPC原理2.共享内存管理 1.共享内存IPC原理 共享内存进程间通信机制主要用于实现进程间大量的数据传输,共享内存是在内存单独开辟的一段内存空间,这段内存空间有自己特有的数据结构,包括访问权限,大小和最近访问的时间等。该数据结构定义如下: //include /usr/include/bit/shm.h struct shmid_ds { ...

香蕉一号 484

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

linux进程间通信快速入门【二】:共享内存编程(mmap、XSI、POSIX)

使用文件或管道进行进程间通信会有很多局限性,比如效率问题以及数据处理使用文件描述符而不如内存地址访问方便,于是多个进程以共享内存的方式进行通信就成了很自然要实现的IPC方案。 LInux给我们提供了三种共享内存的解决方案: mmap内存共享映射。 XSI共享内存。 POSIX共享内存。 mmap内存共享映射 mmap可以将一个文件映射到内存中,在程序里就可以直接使用内存地址对文件内容进行访问,这可以让程序对文件访问更方便。 API: #include <sys/mman.h> void *m

hanhan的博客 1840

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

c++ fork 进程时 共享内存_Linux进程间通信10分钟快速入门

在Linux环境下运行程序,无论是点击桌面上的一个图标,还是在命令行下敲击一个shell命令,Linux系统都会把我们的程序“包装”成一个进程的形式,然后调度运行:每个进程轮流占用CPU一段时间去执行,时间到了就让给其它进程,时间片轮转,只要轮转得速度足够快,就会给用户一种错觉:我们在电脑上一边听歌,一边打字,感觉多个程序在同时运行。不同进程在运行过程中,根据业务需要,进程相互之间也会通信:比如传...

weixin_39945531的博客 102

Linux——进程间通信(2)——共享内存、信号、信号量

文章目录一、共享内存二、使用步骤1.引入库2.读入数据总结 一、共享内存 二、使用步骤 1.引入库 代码如下(示例): import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns import warnings warnings.filterwarnings('ignore') import ssl ssl._create_default_https_context = ssl

jason_stanson的博客 805

Linux进程间通信——使用共享内存

下面将讲解进程间通信的另一种方式,使用共享内存。 一、什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一

ljianhui的专栏 24万+

【Linux】进程间通信——共享内存

共享内存(Shared Memory)是一种进程间通信(IPC)机制,允许多个进程共享同一块物理内存,从而提高数据交换效率。相比其他 IPC 方式(如管道、消息队列等),共享内存具有速度快、低开销的优势,因为数据直接存储在内存中,而无需通过内核进行数据拷贝。共享内存作为一种高效的进程间通信机制,因其直接在内存中操作数据,避免了数据拷贝,提供了快速的数据传输方式。通过shmgetshmatshmctl等函数,Linux 系统为我们提供了灵活的共享内存操作接口。

2301_79969994的博客 5033

Linux进程间通信——共享内存

linux进程间通信——共享内存

strive_mianyang的博客 2385

【Linux】进程间通信——System V共享内存

System V是一种在Linux系统中用于进程间通信(IPC)的机制。它提供了几种不同的通信方式,包括共享内存、消息队列和信号量。System V共享内存是一种高效的进程间通信(IPC)机制,它允许多个进程共享一块物理内存区域,从而避免了数据的复制,显著提高了数据传输速率。

Renswc的博客 2485

【Linux-进程间通信】共享内存

ipcs是一个用于查看 POSIX 系统中进程间通信 (IPC) 资源信息的命令行工具。使用-m选项可以专门查看共享内存 (shared memory) 的相关信息。常用选项描述-m显示共享内存段的信息-q显示消息队列的信息(不与-m一起使用)-s显示信号量的信息(不与-m一起使用-t显示创建时间-p显示创建者的 PID-c显示核心映像的创建者-l显示更详细的列表字段含义key用于访问共享内存段的键值。这个键是由ftok。

2202_75331338的博客 2047
上一篇: Linux系统开发总览
下一篇: Ubuntu共享环境配置
fensnote
博客等级 码龄7年 11粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值