Linux学习笔记:进程间的通信.共享内存shm

共享内存shm

  • 什么是共享内存shm
  • 共享内存的特点
  • 关键函数
    • ftok
    • shmget
    • shmat
    • shmdt
    • shmctl
  • 代码示例

什么是共享内存shm

进程间通信的前提:必须让不同的进程看到同一份资源,并且这个资源是OS提供的

而共享内存(Share memory)就是在内核共享内存区找一块物理内存空间,并允许多个进程共享同一块内存区域的机制

不同于消息队列或管道,共享内存允许进程直接读写共享区域,因此具有较高的性能。通常情况下,共享内存用于需要频繁交换数据的场景,例如图形处理、数据库管理等。

原理图:
在这里插入图片描述
图片来源于bing搜索

共享内存的特点

  • 共享内存的通信方式,不会提供同步机制,共享内存是直接裸露给所有使用者的,因此在使用共享内存的时候一定要注意安全问题
  • 共享内存是所有进程通信中速度最快的,因为进程间的这块内存是共享的,因此这块内存中的数据是不需要进行拷贝等操作,每个进程可以直接访问
  • 共享内存一般是可以提供较大的空间的

关键函数

ftok

ftok函数可以理解为file to key ,在linux下,一切皆文件,因此共享内存也可以被看成是文件,这里的file就指的是共享的那块物理内存,而ftok 函数用于生成一个与给定路径名和项目标识符相关联的键值(key),用于后续共享内存的创建或连接。
在这里插入图片描述
通常在创建共享内存之前,需要使用 ftok 函数生成一个键值,以确保不同进程能够访问同一块共享内存。

shmget

shmget 函数用于创建共享内存段或获取现有共享内存段的标识符。shmget 函数接受三个参数:键值(key)、大小(size)和标志(flags)。键值通常由 ftok 函数生成,大小是要创建的共享内存段的大小一般为4096的整数倍,标志用于指定创建共享内存段的权限和行为。
在这里插入图片描述
标志位flags一般会用到两个参数 IPC_CREATE 和 IPC_EXCL,一般情况下 IPC_EXCL不单独使用 IPC_CREATE是创建否则获取.

通过 shmget 函数可以创建新的共享内存段,或者获取已经存在的共享内存段的标识符。

shmat

shmat 函数用于将共享内存段连接到调用进程的地址空间,从而可以访问共享内存中的数据。
在这里插入图片描述
shmat 函数接受三个参数:共享内存标识符(shmid)、地址(shmaddr)和标志(flags)。共享内存标识符是由 shmget 函数返回的共享内存段标识符,地址是要将共享内存映射到的地址,如果为 NULL,则由系统自动选择,标志用于指定连接共享内存的行为。
最终返回一个指向共享内存的指针,用于后续对共享内存的访问。
通过 shmat 函数将共享内存连接到进程的地址空间,使得进程可以直接访问共享内存中的数据。

shmdt

shmdt 函数用于从调用进程的地址空间分离共享内存段,停止对共享内存的访问。
在这里插入图片描述
shmdt 函数接受一个参数,即指向共享内存的指针。
通过 shmdt 函数可以停止对共享内存的访问,并释放与之相关的资源。

shmctl

shmctl 函数用于对共享内存进行控制操作,如获取信息、设置权限、删除共享内存等。
在这里插入图片描述
shmctl 函数接受三个参数:共享内存标识符(shmid)、命令(cmd)和缓冲区(buf)。共享内存标识符是由 shmget 函数返回的共享内存段标识符,命令用于指定要执行的控制操作,缓冲区用于存放返回的信息或接收需要设置的参数。
通过 shmctl 函数可以对共享内存进行各种控制操作,如获取信息、设置权限、删除共享内存等。

代码示例

在下面的代码示例中,我创建了两个.cc文件 server.cc 和 client.cc ,在这两个cpp文件身生成的进程中有一段共享内存来传递信息,并插入命名管道使之具有更明显的分工效果

server.cc

#include<iostream>
#include<sys/ipc.h> //Inter-Process Communication
#include<sys/shm.h>
#include<cstring>#include"comm.hpp"int main()
{   //创建管道bool r = Makefifo();if(!r) return 1;//创建唯一的k用于两进程找到这段共享内存的标识 调用函数 ftokkey_t k = GetKey();// 创建共享内存   int shmid = CreatShm(k);//挂载共享内存std::cout<<"开始将shm映射到我的进程中"<<std::endl;char* s = (char*)shmat(shmid,nullptr,0); //根据客户端输入内容来从共享内存中获取内容int fd = open(filename.c_str(),O_RDONLY);while(true){int code = 0;ssize_t n = read(fd,&code,sizeof(code));if(n > 0){std::cout<<"共享内存:"<< s << std::endl;}else if(n == 0){break;}}//将shm从进程中移除shmdt(s);std::cout<<"将shm从进程中移除"<<std::endl;//删除shmshmctl(shmid,IPC_RMID,nullptr);std::cout<<"将shm从os中删除"<<std::endl;return 0;
}

client.cc

#include<iostream>
#include<sys/ipc.h> //Inter-Process Communication
#include<sys/shm.h>
#include<cstring>#include"comm.hpp"int main()
{   //获取kkey_t k = GetKey();//获取shmint shmid = GetShm(k);//挂载共享内存到进程char* s = (char*)shmat(shmid,nullptr,0);//获取管道fdint wfd = open(filename.c_str(),O_WRONLY);//对共享内存和管道进行输入,若写入共享内存,在通知管道可读char c = 'a';for(;c <= 'z';c++){s[c - 'a'] = c;int code = 1;write(wfd,&code,sizeof(code));std::cout<<"write " << c << " done" << std::endl;sleep(1);}//删除管道unlink(filename.c_str()); //将shm从进程中移除shmdt(s);std::cout<<"将shm从进程中移除"<<std::endl; //因文共享内存机制的原因,两个进程是不会因此而同步,对两个进程说就是一个公共空间,里面的内容谁想用就用,想改就可以个改return 0;
}

comm.hpp

#pragma once#include<iostream>
#include<string>
#include<fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<unistd.h>const std::string pathname = "/home/cris/vscodef";
const int proj_id = 0x11223344;
const std::string filename = "fifo";const int sh_size = 4096;  //共享内存的大小最好设置成4096的倍数key_t GetKey()
{key_t k = ftok(pathname.c_str(),proj_id);if(k < 0){std::cerr << "errno:" << errno << ",errstring" << strerror(errno) <<std::endl;exit(1);}std::cout<< "key:" << k << std::endl;return k;}int CreatShmHelper(key_t key , int flag)
{//共享内存的生命周期是随内核的   查看共享内存:ipcs -m  删除: ipcrm -m shmid// 调用函数shmget  此函数技能创建又能获取  //一般情况下 IPC_EXCL不单独使用  IPC_CREATE是创建否则获取/// int shmget(key_t key,size_t size ,int shmflg)int shmid = shmget(key,sh_size,flag);if(shmid < 0){std::cerr << "errno:" << errno << ",errstring" << strerror(errno) <<std::endl;exit(2);}std::cout<< "shmid:" << shmid << std::endl;return shmid;
}int CreatShm(key_t key)
{return CreatShmHelper(key,IPC_CREAT|IPC_EXCL|0644);
}int GetShm(key_t key)
{return CreatShmHelper(key,IPC_CREAT);
}bool Makefifo()
{int n = mkfifo(filename.c_str(),0666);if(n < 0){std::cerr << "errno" << errno << ",errstring" << strerror(errno) << std::endl;return false;}return true;
}

Makefile

.PHONY:all
all:client serverclient:client.ccg++ -o $@ $^ -std=c++11
server:server.ccg++ -o $@ $^ -std=c++11.PHONY:clean
clean:rm -f server client fifo

运行效果如图:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ReentrantReadWriteLock(可重入读写锁)源码解读与使用

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java源码解读-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1. 前言 2. 读写锁是什么 3. ReentrantReadWriteLock是什么 4. 源码解…

公文写作笔记

标题 最后一行的日期&#xff0c;后边占4个格子。两个数字占一格。落款单位在日期的正上方。 格式积累 内容&#xff1a; ①开头&#xff1a;缘由 ②主题&#xff1a;对策&#xff08;别人做得好&#xff0c;就借鉴&#xff09; ③结尾&#xff1a;简单的总结&#xff08;字…

聊聊Mysql的两阶段提交

从图中可看出&#xff0c;事务的提交过程有两个阶段&#xff0c;就是将 redo log 的写入拆成了两个步骤&#xff1a;prepare 和 commit&#xff0c;中间再穿插写入bin log&#xff0c;具体如下&#xff1a; prepare 阶段&#xff1a;将 事务的修改写入到 redo log&#xff0c;同…

GitLab(史上最全GitLab安装使用文章!!!)

GitLab 是一个基于网络的Git仓库管理工具&#xff0c;是开源的。基本每个公司都会有属于自己公司内部的GitLab 官方网站&#xff1a;https://about.gitlab.com/ GitLab文档&#xff1a;https://docs.gitlab.cn/jh/install/requirements.html 安装 所需配置 这里采用Cento…

TMS320F280049 EQEP模块--QWDOG UTIME(4)

QWDOG功能框图 下图是watchdog的功能框图。在WDE使能后&#xff0c;16bit宽的计数器QWDTMR在64分频的时钟下开始计数&#xff0c;在QCLK时会被重置。当QWDTMR到达QWDPRD时会置位WTO并产生WDTOUT事件。 所以该watchdog是用来检测电机是否转动的。假设电机停止转动&#xff0c;则…

stm32 hid自定义接收发送程序开发过程记录

cubleMX配置如下 修改端点描述符一次传输的数据大小 根据cubelMX标准在这里修改 编译错误 直接修改&#xff08;因为没有使用nodef &#xff09;编译通过 修改报告描述符&#xff08;默认的描述符无法传输数据&#xff09; 参考&#xff1a;USB协议详解第10讲&#xff08;USB描…

CUDA CPP Unity Compute Shader Linear Algebra

为学 开始一个新的学习计划&#xff0c;涵盖&#xff1a; 主题学习内容CUDAProfessional CUDA C Programming/NVIDIA CUDA初级教程视频(周斌)CCPrimer / The Cherno CPPUnity Compute ShaderUdemy Learn to Write Unity Compute ShadersLinear AlgebraMIT 18.06 Prof.Gilbert…

【RabbitMQ】可靠性策略(幂等,消息持久化)

MQ可靠性策略 发送者的可靠性问题生产者的重连生产者确认 MQ的可靠性数据持久化Lazy Queue 消费者的可靠性问题消费者确认机制消息失败处理 业务幂等性简答问题 发送者的可靠性问题 生产者的重连 可能存在由于网络波动&#xff0c;出现的客户端连接MQ失败&#xff0c;我们可以…

USB HID报告描述符学习

参考资料 HID 报告描述符 (qq.com)https://mp.weixin.qq.com/s?__bizMzU1ODI3MzQ1MA&mid2247485748&idx1&sn112bd8014eb96b03308b3b808549e8d4&chksmfc284ff1cb5fc6e770c2d2ece46c17bf2529901b45a357938978fa62163723556ad497b05c47&cur_album_id3340417…

活性炭复合纳米纤维膜

活性炭复合纳米纤维膜是一种结合了活性炭和纳米纤维技术的新型复合材料。这种材料通常通过特定的制备工艺&#xff0c;如静电纺丝技术&#xff0c;将活性炭纳米纤维与其他材料&#xff08;如TiO2、聚合物等&#xff09;结合在一起&#xff0c;形成具有良好结构和功能的薄膜。 活…

【hana】hana1.0单容器常用命令

基础命令 服务 要先切换到hana用户下 查看服务是否启动 HDB info启动服务 HDB start获取instance_id su - {hana_user} echo $TINSTANCE数据库 连接数据库 hdbsql -u system -p xxxxxx -i {instance_id}获取数据库状态 SELECT DATABASE_NAME, ACTIVE_STATUS FROM M_DA…

Notion是什么,Notion软件下载,Notion官方网站在哪里?国内用户Notion怎么订阅升级会员?

Notion是什么 Notion&#xff0c;一款强大的多功能工具&#xff0c;可用于组织笔记、任务、项目、数据库和文档等。 Notion软件下载 这个到Notion官方网站下载就可以了。 怎么订阅Notion会员 注册好了Notion的账号&#xff0c;来到首页&#xff0c;点击设置&#xff0c;左边…