【Linux学习笔记】进程间通信之共享内存

【Linux学习笔记】进程间通信之共享内存

在这里插入图片描述

🔥个人主页大白的编程日记

🔥专栏Linux学习笔记


文章目录

  • 【Linux学习笔记】进程间通信之共享内存
    • 前言
    • 一. system V共享内存
      • 1.1 共享内存数据结构
      • 1.2 共享内存函数
      • 1.3 共享内存实现通信
      • 1.4 借助管道实现访问控制版的共享内存
    • 后言

前言

哈喽,各位小伙伴大家好!上期我们讲了进程间通信之管道 今天我们讲的是进程间通信之共享内存。话不多说,我们进入正题!向大厂冲锋!
在这里插入图片描述

一. system V共享内存

共享内存区是最快的IPC形式。⼀旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执⾏进⼊内核的系统调⽤来传递彼此的数据

共享内存示意图

在这里插入图片描述

1.1 共享内存数据结构

struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms */
int shm_segsz; /* size of segment
(bytes) */
__kernel_time_t shm_atime; /* last attach time */
__kernel_time_t shm_dtime; /* last detach time */
__kernel_time_t shm_ctime; /* last change time */
__kernel_ipc_pid_t shm_cpid; /* pid of creator */
__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
unsigned short shm_nattch; /* no. of current
attaches */
unsigned short shm_unused; /* compatibility */
void shm_unused2; / ditto - used by
DIPC */
void shm_unused3; / unused */
};

1.2 共享内存函数

shmget函数

功能:⽤来创建共享内存
原型
int shmget(key_t key, size_t size, int shmflg);
参数
key:这个共享内存段名字
size:共享内存⼤⼩
shmflg:由九个权限标志构成,它们的⽤法和创建⽂件时使⽤的mode模式标志是⼀样的
取值为IPC_CREAT:共享内存不存在,创建并返回;共享内存已存在,获取并返回。
取值为IPC_CREAT | IPC_EXCL:共享内存不存在,创建并返回;共享内存已存在,出
错返回。
返回值:成功返回⼀个⾮负整数,即该共享内存段的标识码;失败返回-1

shmat函数

功能:将共享内存段连接到进程地址空间
原型
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数
shmid: 共享内存标识
shmaddr:指定连接的地址
shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回⼀个指针,指向共享内存第⼀个节;失败返回-1

说明:

shmaddr为NULL,核⼼⾃动选择⼀个地址
shmaddr不为NULL且shmflg⽆SHM_RND标记,则以shmaddr为连接地址。
shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会⾃动向下调整为SHMLBA的整数倍。
公式:shmaddr - (shmaddr % SHMLBA)
shmflg=SHM_RDONLY,表⽰连接操作⽤来只读共享内存

shmdt函数

功能:将共享内存段与当前进程脱离
原型
int shmdt(const void *shmaddr);
参数
shmaddr: 由shmat所返回的指针
返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段

shmctl函数

功能:⽤于控制共享内存
原型
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数
shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作(有三个可取值)
buf:指向⼀个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1

在这里插入图片描述

1.3 共享内存实现通信

测试代码结构

# ls
client.c comm.c comm.h Makefile server.c
# cat Makefile
.PHONY:all
all:server client
client:client.c comm.c
gcc -o $@ $^
server:server.c comm.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f client server
1

comm.h

#ifndef _COMM_H_
#define _COMM_H_
# include <stdio.h>
# include <sys/types.h>
# include <sys/ipc.h>
# include <sys/shm.h>
# define PATHNAME "."
# define PROJ_ID 0x6666
int createShm(int size);
int destroyShm(int shmid);
int getShm(int size);
# endif

comm.c

#include "comm.h"
static int commShm(int size, int flags)
{
key_t key = ftok(PATHNAME, PROJ_ID);
if(key < 0){
perror("ftok");
return -1;
}
int shmid = 0;
if( (shmid = shmget(key, size, flags)) < 0){
perror("shmget");
return -2;
}
return shmid;
}
int destroyShm(int shmid)
{
if(shmctl(shmid, IPC_RMID, NULL) < 0){
perror("shmctl");
return -1;
}
return 0;
}
int createShm(int size)
{
return commShm(size, IPC_CREAT|IPC_EXCL|0666);
}
int getShm(int size)
{
return commShm(size, IPC_CREAT);
}

server.c

#include "comm.h"
int main()
{
int shmid = createShm(4096);
char *addr = shmat(shmid, NULL, 0);
sleep(2);
int i = 0;
while(i++<26){
printf("client# %s\n", addr);
sleep(1);
}
shmdt(addr);
sleep(2);
destroyShm(shmid);
return 0;
}

client.c

#include "comm.h"
int main()
{
int shmid = getShm(4096);
sleep(1);
char *addr = shmat(shmid, NULL, 0);
sleep(2);
int i = 0;
while(i<26){
addr[i] = 'A'+i;
i++;
addr[i] = 0;
sleep(1);
}
shmdt(addr);
sleep(2);
return 0;
}

1.4 借助管道实现访问控制版的共享内存

在这里插入图片描述

  • Comm.hpp
以下是提取的代码:```cpp
#pragma once#include <fcntl.h>#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <cassert>
#include <cstdio>
#include <ctime>
#include <cstring>
#include <iostream>
#include <string>using namespace std;#define Debug 0
#define Notice 1
#define Warning 2
#define Error 3
const std::string msg[] = {"Debug","Notice","Warning","Error"
};std::ostream &Log(std::string message, int level) {std::cout << " | " << (unsigned)time(nullptr) << " | " << msg[level] << " | " << message;return std::cout;
}#define PATH_NAME "/home/hyb"
#define PROJ_ID 0x66
#define SHM_SIZE 4096  // 共享内存的大小,最好是页(PAGE: 4096)的整数倍
#define FIFO_NAME "./fifo"class Init {
public:Init() {umask(0);int n = mkfifo(FIFO_NAME, 0666);assert(n == 0);(void)n;Log("create fifo success", Notice) << "\n";}~Init() {unlink(FIFO_NAME);Log("remove fifo success", Notice) << "\n";}
};#define READ O_RDONLY
#define WRITE O_WRONLY
int OpenFIFO(std::string pathname, int flags) {int fd = open(pathname.c_str(), flags);assert(fd >= 0);return fd;
}void CloseFifo(int fd) {close(fd);
}void Wait(int fd) {Log("等待中....", Notice) << "\n";uint32_t temp = 0;ssize_t s = read(fd, &temp, sizeof(uint32_t));assert(s == sizeof(uint32_t));(void)s;
}void Signal(int fd) {uint32_t temp = 1;ssize_t s = write(fd, &temp, sizeof(uint32_t));assert(s == sizeof(uint32_t));(void)s;Log("唤醒中....", Notice) << "\n";
}string TransToHex(key_t k) {char buffer[32];sprintf(buffer, sizeof buffer, "0x%x", k);return buffer;
}
  • ShmServer.cc
以下是提取的代码:```cpp
#include "Comm.hpp"
Init init;int main() {// 1. 创建公共的Key值key_t k = ftok(PATH_NAME, PROJ_ID);assert(k != -1);Log("create key done", Debug) << " server key : " << TransToHex(k) << endl;// 2. 创建共享内存 -- 建议要创建一个全新的共享内存 -- 通信的发起者int shmid = shmget(k, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);if (shmid == -1) {perror("shmget");exit(1);}Log("create shm done", Debug) << " shmid : " << shmid << endl;// 3. 将指定的共享内存,挂接到自己的地址空间char *shmaddr = (char*)shmat(shmid, nullptr, 0);Log("attach shm done", Debug) << " << shmid << endl;// 4. 访问控制int fd = OpenFIFO(FIFO_NAME, O_RDONLY);while (true) {// 阻塞Wait(fd);// 临界区printf("%s\n", shmaddr);if (strcmp(shmaddr, "quit") == 0)break;}CloseFifo(fd);// 5. 将指定的共享内存,从自己的地址空间中去关联int n = shmdt(shmaddr);assert(n != -1);(void)n;Log("detach shm done", Debug) << " << shmid << endl;// 6. 删除共享内存, IPC_RMID即便是有进程和当下的shm挂接,依旧删除共享内存n = shmctl(shmid, IPC_RMID, nullptr);assert(n != -1);(void)n;Log("delete shm done", Debug) << " << shmid << endl;return 0;
}
  • ShmClient.cc
以下是提取的代码:```cpp
#include "Comm.hpp"int main() {// 1. 创建公共的key值key_t k = ftok(PATH_NAME, PROJ_ID);if (k < 0) {Log("create key failed", Error) << " client key : " << TransToHex(k) << endl;exit(1);}Log("create key done", Debug) << " client key : " << TransToHex(k) << endl;// 2. 获取共享内存int shmid = shmget(k, SHM_SIZE, 0);if (shmid < 0) {Log("create shm failed", Error) << " client key : " << TransToHex(k) << endl;exit(2);}Log("create shm success", Error) << " client key : " << TransToHex(k) << endl;// 3. 挂接共享内存char* shmaddr = (char*)shmat(shmid, nullptr, 0);if (shmaddr == nullptr) {Log("attach shm failed", Error) << " client key : " << TransToHex(k) << endl;exit(3);}Log("attach shm success", Error) << " client key : " << TransToHex(k) << endl;// 4. 写int fd = OpenFIFO(FIFO_NAME, O_WRONLY);while (true) {ssize_t s = read(0, shmaddr, SHM_SIZE - 1);if (s > 0) {shmaddr[s - 1] = 0;Signal(fd);if (strcmp(shmaddr, "quit") == 0)break;}}CloseFifo(fd);// 5. 去关联int n = shmdt(shmaddr);assert(n != -1);Log("detach shm success", Error) << " client key : " << TransToHex(k) << endl;return 0;
}

后言

这就是进程间通信之共享内存。大家自己好好消化!今天就分享到这! 感谢各位的耐心垂阅!咱们下期见!拜拜~

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

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

相关文章

郭碧婷闯入女团赛道 与刘忻张予曦蔡诗芸组成ROLLING SISTERS

近日&#xff0c;郭碧婷与刘忻、张予曦、蔡诗芸组成的女团ROLLING SISTERS正式官宣&#xff0c;并发布《Rolling Life》《Alpha》两首单曲&#xff01; 此次几位姐姐的组合让大家眼前一亮&#xff0c;尤其是郭碧婷造型颠覆以往。银灰色挑染短发搭配棱角分明的黑色烟熏妆&#x…

2025再升级:医疗数智立体化体系V2.0架构简介

在医疗数智立体化体系第一版基础上,融入量子物理的第一性原理计算、人工智能(AI)、高性能云计算(HPC)和标准化机器人自动化整合成“医疗数智立体化体系2.0”,代表了医疗研发未来的重要发展方向。这个体系的核心在于深度融合物理世界规律、智能计算与自动化执行,为医疗AI…

Day40 训练和测试的规范写法

目录 一、彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中 单通道图片的规范写法 彩色图片的规范写法 二、展平操作&#xff1a;除第一个维度batchsize外全部展平 图像任务中的张量形状 NLP任务中的张量形状 1. Flatten操作 2. view/reshape操作 总结 三…

Linux 文件 I/O 与标准 I/O 缓冲机制详解

一、什么是标准 I/O&#xff1f;&#xff08;FILE* 接口&#xff09; 标准 I/O 是 C 标准库为我们提供的一套高级文件操作接口&#xff0c;核心基于结构体 FILE&#xff0c;常见函数如&#xff1a; fopen() / fclose() fread() / fwrite() fprintf() / fscanf() fflush() /…

C++的前世今生-C++11

C98&#xff08;ISO/IEC 14882:1998&#xff09; C98 是 C 的第一个标准化版本&#xff08;ISO/IEC 14882:1998&#xff09;&#xff0c;它正式确立了 C 的核心语言特性和标准库。以下是 C98 的主要特性总结&#xff1a; 一、核心语言特性** 模板&#xff08;Templates&…

词编码模型怎么进行训练的,输出输入是什么,标签是什么

词编码模型怎么进行训练的,输出输入是什么,标签是什么 词编码模型的训练本质是通过数据驱动的方式,将离散的文本符号映射为连续的语义向量。 一、训练机制:从符号到向量的映射逻辑 1. 核心目标 将单词/子词(Token)映射为低维向量,使语义相关的词在向量空间中距离更近…

【Linux指南】文件管理高级操作(复制、移动、查找)

引言 在Linux系统管理中&#xff0c;文件的复制、移动与查找是比基础操作更进阶的核心技能&#xff0c;它们构成了高效管理文件系统的"三驾马车"。当我们需要备份重要数据、重构目录结构或在庞大的文件系统中定位目标文件时&#xff0c;cp、mv、find等命令将成为最得…

【栈】-----【小C的记事本】

小C的记事本 题目描述 小C最近学会了 Java 小程序的开发&#xff0c;他很开心&#xff0c;于是想做一个简单的记事本程序练练手。 他希望他的记事本包含以下功能&#xff1a; append(str)&#xff1a;向记事本插入字符串 str&#xff08;英文字符&#xff09;。delete(k)&am…

技能系统详解(2)——特效表现

特效会有个EffectManager用于统一管理所有特效&#xff0c;技能特效只是各类特效中的一种 EffectManager需要提供特效的创建&#xff0c;返回被封装为EffectHandle 每类特效都有各种不同的配置参数&#xff0c;这些配置参数会传递给EffectManager用于生成EffectHandler 为支…

12.OpenCV—基础入门

01读取图像 02创建空白图像 03保存图像 04更改图像亮度 05更改图像对比度 06灰度直方图均衡 07彩色直方图均衡 08五种滤波方式 09形态学操作 10仿射变换 11角度缩放仿射变换 12透视变换 13坐标映射 14模板匹配 15多模板匹配 16查找轮廓线 17轮廓线匹配 17绘制…

【Python】Python之什么是生成器?什么是迭代器?

目录 专栏导读前言什么是迭代器&#xff08;Iterator&#xff09;&#xff1f;迭代器的定义迭代器协议可迭代对象 vs 迭代器自定义迭代器迭代器的优势 什么是生成器&#xff08;Generator&#xff09;&#xff1f;生成器的定义生成器函数生成器表达式复杂的生成器示例生成器的状…

Python中实现简单爬虫并处理数据

在当今数据驱动的时代&#xff0c;能够从互联网上高效地抓取信息变得越来越重要。Python因其简洁易学的特性&#xff0c;成为了编写网络爬虫的首选语言之一。接下来&#xff0c;我将介绍如何使用Python来实现一个基础的网络爬虫&#xff0c;并对收集到的数据进行初步处理。 首先…

免费wordpress主题网

免费WordPress主题网 WP模板牛 WP模板牛是一个提供免费WordPress主题的网站&#xff0c;用户可以在这里找到大量高质量的模板&#xff0c;适用于各种网站类型。该网站致力于为用户提供简单、高效的建站体验。 官网链接&#xff1a; https://wpniu.com 建站哥模板 建站哥模板…

为什么需要MyBatis-Plus条件构造器?

目录 前言 一、传统SQL编写的痛点 二、条件构造器的核心优势 1. 防SQL注入&#xff08;安全性&#xff09; 2. 面向对象编程&#xff08;可读性&#xff09; 3. 动态条件构建&#xff08;灵活性&#xff09; 4. 数据库无关性&#xff08;可移植性&#xff09; 三、典型应…

【从零学习JVM|第九篇】常见的垃圾回收算法和垃圾回收器

前言&#xff1a; 我们知道在堆内存中&#xff0c;会有自动的垃圾回收功能&#xff0c;那今天这篇文章将会向你介绍&#xff0c;这个功能实现的方式&#xff0c;还有实现的对象&#xff0c;接下来就由我来给你们详细介绍垃圾回收的算法和实现算法的回收器。 目录 前言&#…

品牌窜货治理解决方案

在渠道网络的暗潮中&#xff0c;窜货犹如隐秘的漩涡&#xff0c;某知名白酒品牌曾因区域窜货导致终端价格体系崩溃&#xff0c;半年内损失超3亿元。窜货行为不仅破坏市场秩序&#xff0c;更会引发信任危机。随着电商平台的多元化与分销层级的复杂化&#xff0c;品牌方亟需构建一…

车载电子电器架构 --- 法律和标准对电子电气架构的影响

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

一种通用跨平台实现SEH的解决方案

一. 前言 众所周知&#xff0c;在软件的代码中&#xff0c;处理软件本身的逻辑只要大约1/3的代码&#xff0c;另外2/3的代码实际上是在处理各种各样的异常情况。 这些异常情况一方面是因为不同用户之间不同的硬件软件环境要处理。另一方面是程序中可能出现的bug。比较典型的情…

25.6.19学习总结

什么是堆&#xff08;Heap&#xff09;&#xff1f; 堆是一种特殊的树形数据结构&#xff0c;它满足以下两个主要属性&#xff1a; 结构性&#xff08;完全二叉树&#xff09;&#xff1a; 堆总是一个完全二叉树 (Complete Binary Tree)。这意味着&#xff0c;除了最后一层&am…

【前后前】导入Excel文件闭环模型:Vue3前端上传Excel文件,【Java后端接收、解析、返回数据】,Vue3前端接收展示数据

【前后前】导入Excel文件闭环模型&#xff1a;Vue3前端上传Excel文件&#xff0c;【Java后端接收、解析、返回数据】&#xff0c;Vue3前端接收展示数据 一、Vue3前端上传&#xff08;导入&#xff09;Excel文件 ReagentInDialog.vue <script setup lang"ts" na…