進程間通信(共享內存)

目錄

前置:

一 原理

二 API

1. shmgetr

2. shmctl

3. 指令操作

2. 刪除

3. 掛接

4. 斷開掛接

三 demo代碼

四 共享內存的特征


前置:

1.前面說的不管是匿名管道還是命名管道都是基于文件的思想構建的一套進程間通信的方案,那有沒有完全從0單獨設計一套呢?

2. 共享內存作為 system v 標準,是由操作系統自主從0搭建的一套進程間通信機制,相對于管道而言也更快,那么下面來看看具體是怎么實現的。

一 原理

1. 進程之間通信之前必須要看到同一份資源,比如管道,看到同一個管道文件(路徑),子進程繼承父進程文件描述符。

2. 共享內存其實是在內存中開辟一段空間,并把起始地址映射到虛擬地址空間的共享區當中,訪問這個虛擬地址也就訪問到內存上的空間了,那么2個毫不相干的進程怎么看到這個共享內存呢?

3. 之前說的動態庫,在程序運行期間在內存中尋找庫文件,找不到在去磁盤上加載,所以在內存中有很多的動態庫,勢必也要管理維護起來并且提供一個字段來標識這個實例,共享內存也同樣如此,在內存中也有個結構進行維護并標識起來。

4. 讓不同進程看到同一份標識,系統提供了一個API

#include <sys/types.h>
#include <sys/ipc.h>key_t ftok(const char *pathname,  // 隨便傳入路徑int proj_id            // 隨便傳入一個id// key_t -> int);

1. 傳入一個路徑和id并通過算法形成一個key_t結構,本質是int類型,算法是固定的,所以不同的進程傳入相同的字符串和id得到的key_t都是一樣的,這是用戶傳入數據生成的。

2. 返回值為-1錯誤,其他均正確。

所以不同的進程傳入相同的路徑和id就能看到同一個共享內存了。

5. 建立共享內存的映射,然后就需要進行把進程和共享內存進行掛接,也就是綁在一起,進行后續通信,結束在斷開掛接。

6. 共享內存只有創建和掛接/斷開掛接/釋放共享內存的時候使用了系統調用,通信的時候不需要,所以直接在用戶層直接向物理內存寫入數據,是進程間通信里最快的,僅需一次拷貝物理內存里的數據。

二 API

1. shmgetr
#include <sys/ipc.h>
#include <sys/shm.h>int shmget(key_t key,    // 用戶生成的 key 值 size_t size,  // 共享內存的大小int shmflg    // 選項: 創建/獲取....);// 返回值: 內核維護的 shmid 值,用來管理共享內存的結構
2. shmctl
#include <sys/ipc.h>
#include <sys/shm.h>int shmctl(int shmid,            // shmget的返回值int cmd,              // 對共享內存: 刪除/修改等操作struct shmid_ds *buf  // 共享內存的結構里的字段);
// 返回值: 成功為0,失敗-1

為什么有了 key ,還要有 shmid ?key是用戶形成的只是用來獲取和創建共享內存的,并不能對已經存在的共享內存進行字段修改/結構修改等,只有shmid能操作,本質就是 shmid 屬于內核提供的,key是有用戶提供的,他們的功能側重點不同,用戶管用戶,內核管內核,變相的解耦。?

3. 指令操作

1. 查看

ipcs -m // 共享內存相關信息
ipcs -q // 消息隊列相關信息
ipcs -s // 信號量相關信息

查詢到的字段

key:? ? 用戶形成的隨機值,用來獲取,創建訪問共享內存。

shmid:shmget的返回值,用來管理共享內存結構的。

owner:誰創建的。

perms:權限是什么。

bytes: 共享內存多大。

nattch:誰掛接上了。

status: 狀態標識。

2. 刪除
ipcrm -m/q/s shmid
3. 掛接
#include <sys/types.h>
#include <sys/shm.h>void *shmat(int shmid,            // shmget的返回值const void *shmaddr,  // 共享內存的起始地址int shmflg            // 權限設置);
4. 斷開掛接
#include <sys/types.h>
#include <sys/shm.h>int shmdt(const void *shmaddr // shmat的返回值);

三 demo代碼

#include <iostream>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <cstring>// htok 用來形成隨機的 key_t
const static std::string pathkey = "/home/CD/linux/shared_memory";
const static int projid = 123456;// 區分創建者和使用者
const static std::string Create = "Create";
const static std::string User = "User";// 共享內存大小
const int shmbuff = 4096;// 轉16進制
std::string to_hex(int val)
{char buff[1024] = {0};snprintf(buff, 1024, "0x%x", val);return buff;
}// SHM類
class SHM
{
private:// 進行掛接bool Shmat(){_buff = shmat(_shmid, nullptr, 0);if (_buff == (void *)-1)return false;return true;}// 創建共享內存并獲取 shmidbool Createshmid(){_shmid = shmget(_key, shmbuff, IPC_CREAT | IPC_EXCL | 0666);if (_shmid == -1){std::cout << "shmgid create failed" << std::endl;return false;}return true;}// 獲取已經存在的共享內存的shmidbool Getshmid(){_shmid = shmget(_key, shmbuff, IPC_CREAT);if (_shmid == -1){std::cout << "shmget get failed" << std::endl;return false;}std::cout << _shmid << std::endl;return true;}public:// 構造對象SHM(const std::string &path, int proj_id, const std::string &who): _path(path), _proj_id(proj_id), _who(who), _buff(nullptr){_key = ftok(_path.c_str(), proj_id);if (_key == -1){std::cout << "ftok failed" << std::endl;exit(-1);}}// 創建共享內存/獲取共享內存shmid/掛接共享內存/獲取共享內存的起始地址void *run(){if (_who == Create){if (Createshmid() == false)exit(-2);if (Shmat() == false){std::cout << "Shmat failed" << std::endl;exit(-3);}}else{if (Getshmid() == false)exit(-2);if (Shmat() == false){std::cout << "Shmat failed" << std::endl;exit(-3);}}memset(_buff, 0, shmbuff);return _buff;}// 釋放共享內存/斷開掛起~SHM(){if (_who == Create){int n = shmctl(_shmid, IPC_RMID, nullptr);if (n == -1){std::cout << "ftok failed" << std::endl;exit(-3);}}if (_buff != nullptr)shmdt(_buff);}private:std::string _path;int _proj_id;std::string _who;int _shmid;key_t _key;void *_buff;
};

四 共享內存的特征

1. 由于通信是在用戶層直接寫到物理內存,沒有系統調用,所以不像管道有read/write接口,read的時候沒有數據內核會阻塞,而共享內存則沒有任何保護機制,也就是無同步無互斥,所以需要應用層進行處理。

2. 共享內存是進程間通信里最快的,用戶層直接通過共享映射的虛擬地址寫入即可,無任何系統調用。

3. 共享內存的大小是 4k 為基本單位的,不符合倍數就向上取整。

4. 共享內存的生命周期隨內核,除非手動代碼/指令進行釋放。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/82904.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/82904.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/82904.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

詳解GPU

詳解GPU GPU&#xff08;圖形處理器&#xff09;就像電腦里的 “圖形小能手”&#xff0c;原本主要用來畫畫&#xff08;渲染圖形&#xff09;&#xff0c;現在還能幫忙干很多雜活&#xff08;并行計算&#xff09; 一、先認識 GPU 的 “鑰匙”&#xff1a;驅動和開發工具 裝驅…

體育遇上AI:解讀新一代智能閱讀產品

在信息過載的今天&#xff0c;體育迷們時常面對這樣的困擾&#xff1a;如何從海量賽事新聞、數據分析和深度評論中高效獲取自己真正關心的內容&#xff1f;體育AI閱讀產品正成為解決這一痛點的關鍵鑰匙——它融合人工智能技術與體育內容生態&#xff0c;為球迷提供智能化、個性…

外網訪問可視化工具 Grafana (Linux版本)

Grafana 是一款強大的可視化監控指標的展示工具&#xff0c;可以將不同的數據源數據以圖形化的方式展示&#xff0c;不僅通用而且非常美觀。它支持多種數據源&#xff0c;如 prometheus 等&#xff0c;也可以通過插件和 API 進行擴展以滿足各種需求。 本文將詳細介紹如何在本地…

Java開發經驗——阿里巴巴編碼規范實踐解析4

摘要 本文主要介紹了阿里巴巴編碼規范中關于日志處理的相關實踐解析。強調了使用日志框架&#xff08;如 SLF4J、JCL&#xff09;而非直接使用日志系統&#xff08;如 Log4j、Logback&#xff09;的 API 的重要性&#xff0c;包括解耦日志實現、統一日志調用方式等好處。同時&…

各個鏈接集合

golang學習&#xff5e;&#xff5e;_從數組中取一個相同大小的slice有成本嗎?-CSDN博客 框架 golang學習&#xff5e;&#xff5e;_從數組中取一個相同大小的slice有成本嗎?-CSDN博客 golang k8s學習_容器化部署和傳統部署區別-CSDN博客 K8S rabbitmq_rabbitmq 廣播-CSD…

Cesium 展示——獲取鼠標移動、點擊位置的幾種方法

文章目錄 需求分析:這里我們用到了幾種常見的鼠標事件1. 獲取鼠標移動的位置2. 獲取鼠標點擊的位置3. 添加面4. 示例代碼需求 獲取指定斷面的 label 分析:這里我們用到了幾種常見的鼠標事件 1. 獲取鼠標移動的位置 viewer.screenSpaceEventHandler.setInputAction((moveme…

技術分享 | Oracle SQL優化案例一則

本文為墨天輪數據庫管理服務團隊第70期技術分享&#xff0c;內容原創&#xff0c;作者為技術顧問馬奕璇&#xff0c;如需轉載請聯系小墨&#xff08;VX&#xff1a;modb666&#xff09;并注明來源。 一、問題概述 開發人員反映有條跑批語句在測試環境執行了很久都沒結束&…

$3 #12階段三小結Java se

$3 #12 階段三小結 Java se 基本沒有新學什么知識點 感覺 基礎語法 和高級語法 已經學完了 現在就是得學習 一些企業開發的框架 以及項目架構的思維 比如一個產品 從需求分析 到功能模塊設計 到接口文檔定義 數據庫建立 前端接口頁面設計 后端接口開發的步驟 然后現在比…

華為云Flexus+DeepSeek征文 | 初探華為云ModelArts Studio:部署DeepSeek-V3/R1商用服務的詳細步驟

華為云FlexusDeepSeek征文 | 初探華為云ModelArts Studio&#xff1a;部署DeepSeek-V3/R1商用服務的詳細步驟 前言一、華為云ModelArts Studio平臺介紹1.1 ModelArts Studio介紹1.2 ModelArts Studio主要特點1.3 ModelArts Studio使用場景1.4 ModelArts Studio產品架構 二、訪問…

易經六十四卦象解釋數據集分享!智能體知識庫收集~

今天給大家分享一個易經六十四卦象解釋數據集 &#xff0c;繼續來積累AI相關的資料。 六十四卦&#xff0c;記載于《易經》&#xff0c;每一卦的圖像均由兩個八卦上下組合而成&#xff0c;每一卦各有六個爻。南宋朱熹說&#xff0c;先畫八卦于內&#xff0c;后畫八卦于外&#…

1 μs = 10?? s

1 s 10? s 1 ms 10? s 1 s 10?? s 1 ns 10?? s 1 ps 10? s 1 fs 10?? s ?? 時間單位&#xff08;十進制&#xff09; 符號單位名稱10 的冪次s秒&#xff08;second&#xff09;10?ms毫秒&#xff08;millisecond&#xff09;10?s微秒&#xff08;microseco…

webrtc初了解

1. webrtc的簡介 一、WebRTC 是什么&#xff1f; Web Real-Time Communication&#xff08;網頁實時通信&#xff09;&#xff0c;是瀏覽器原生支持的實時音視頻通信技術&#xff0c;無需安裝插件或客戶端&#xff0c;可直接在瀏覽器之間實現點對點&#xff08;P2P&#xff09…

從數據持久化到網絡通信與OpenCV:Qt應用程序開發的深度探索與實戰

文章目錄 前言一、QSettings&#xff1a;輕量級數據持久化方案1.1 QSettings 主要特點1.2 QSettings 常用函數整理 二、數據庫2.1 連接SQLite數據庫2.2 建表2.3 增刪改 三、網絡編程3.1 網絡分層3.2 IP地址3.3 端口號3.4 基于TCP的Socket通信3.4 相關接口3.4.1核心類3.4.2 通信…

經典SQL查詢問題的練習第一天

首先有三張表&#xff0c;學生表、課程表、成績表 student:studentId,studentName; course:courseId&#xff0c;courseName,teacher; score:score,studentId,courseId; 接著有以下幾道題目&#xff1a; ①查詢課程編號為‘0006’的總成績&#xff1a; 首先總成績&#x…

企業級網絡管理實戰:Linux、云與容器的深度融合與優化

在數字化轉型浪潮下&#xff0c;企業網絡架構日益復雜&#xff0c;Linux系統、云計算與容器技術成為構建高效、靈活網絡的核心要素。本文將從技術原理、實踐方案、優化策略三個維度&#xff0c;深度解析企業級網絡管理中的關鍵技術&#xff0c;助力企業打造穩定、安全、可擴展的…

信號與系統速成-1.緒論

b站浙大教授雖然講的比較細&#xff0c;但是太慢了&#xff0c;不適合速成 祖師爺奧本海姆的MIT課程好像和我們教材的版本不太匹配&#xff0c;但是講的很不錯 慕課上也有很多資源&#xff0c;比如信號與系統 - 網易云課堂 同站博主籬笆外的xixi的文章也挺不錯 最終我還是選…

緩存架構方案:Caffeine + Redis 雙層緩存架構深度解析

在高并發、低延遲的現代互聯網系統中&#xff0c;緩存是提升系統性能和穩定性的重要手段。隨著業務復雜度的增長&#xff0c;單一緩存方案&#xff08;如僅使用Redis或僅使用本地緩存&#xff09;已難以滿足高性能與一致性需求。 本文將圍繞 Caffeine Redis 的雙層緩存架構展…

【Elasticsearch】track_total_hits

在 Elasticsearch 中&#xff0c;track_total_hits 是一個查詢參數&#xff0c;用于控制是否精確計算搜索結果的總命中數&#xff08;total hits&#xff09;。默認情況下&#xff0c;Elasticsearch 在某些情況下可能會對總命中數進行近似計算&#xff0c;以提高性能。track_to…

智能手機上用Termux安裝php+Nginx

Termux的官方網站&#xff1a;Termux | The main termux site and help pages. 以下是在 Termux 上安裝和配置 PHP Nginx 的完整流程總結&#xff0c;包含關鍵步驟和命令&#xff1a; 一、安裝依賴 pkg update && pkg upgrade # 更新包列表和系統pkg install nginx p…

電腦開機后出現bootmgr is conmpressed原因及解決方法

最近有網友問我為什么我電腦開機后出現BOOTMGR is compressed&#xff0c;這個提示意思是:意思是啟動管理器被壓縮了&#xff0c;即使重啟也無法正常進入系統。原因有很多&#xff0c;大部分是引導出現問題&#xff0c;或選錯了啟動硬盤所導致的&#xff0c;下面我們來詳細分析…