【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
英文地址,請注明出處:http://en.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…