【linux進程間通信(二)】共享內存詳解以及進程互斥概念

💓博主CSDN主頁:杭電碼農-NEO💓
?
?專欄分類:Linux從入門到精通?
?
🚚代碼倉庫:NEO的學習日記🚚
?
🌹關注我🫵帶你學更多操作系統知識
? 🔝🔝


在這里插入圖片描述

進程間通信

  • 1. 前言
  • 2. 共享內存的原理
  • 3. 實現共享內存的基本步驟
  • 4. 共享內存編碼實現
  • 5. 進程互斥相關概念
  • 6. 總結

1. 前言

在學習Linux中的程序地址空間時,
善于觀察的同學可能會發現在棧區
和堆區中間有一個共享區,這是用來
干啥的?今天就來揭曉一下!

本章重點:

本篇文章著重介紹進程間通信的一種
方式: 共享內存的概念,接口使用以及
它的底層原理,最后會介紹進程間互斥
的一些基本概念


2. 共享內存的原理

共享內存區是最快的IPC形式。一旦這樣的內存映射到共享它的進程的地址空間,這些進程間數據傳遞不再涉及到內核,換句話說是進程不再通過執行進入內核的系統調用來傳遞彼此的數據

說大白話就是: 共享內存的通信方式就是在物理內存中開辟一份空間,然后將這份空間映射到兩個進程的共享區中,這兩個進程可以直接在自己的地址空間中讀取或寫入數據,不會經過內核,效率很快!

在這里插入圖片描述


3. 實現共享內存的基本步驟

使用shm系統函數來實現這一功能:

  1. 第一步: 獲取key值

要通信的雙方怎樣保證自己看見的是和對方一樣共享內存? -> 通過一個key值來保證,只要兩個進程拿到同一個key值,再用這個key值去創建共享內存,那么它們看見的就是同一份共享內存!

在這里插入圖片描述

使用ftok函數可以形成一個唯一的key值
函數的參數隨意指定,只要保證通信雙方
傳入的參數一樣,就能備注拿到一樣的key

  1. 第二步: 創建/獲取共享內存

通信雙方只需要一方來創建共享內存,另外一方可以直接通過key值獲取到共享內存(畢竟物理內存只需要創建一份),不管是創建還是獲取共享內存使用的都是同一個函數!

在這里插入圖片描述

  1. 第三步: 將共享內存映射到地址空間

當雙方進程都拿到共享內存段的標識碼后,此時需要將這份共享空間從物理地址映射到進程自己內部的地址空間中,方便后續使用!

在這里插入圖片描述

  1. 第四步: 使用完后將共享內存與進程去關聯

值得注意的是,共享內存使用完后和指針一樣需要"釋放",否則會導致內存泄漏問題

在這里插入圖片描述

  1. 第五步: 刪除共享內存

將共享內存與進程去關聯后,并不代表它就被刪除了,共享內存的生命周期是隨內核的,而我們的云服務器是永遠不會關閉的,如果不刪除共享內存,將來能使用的空間會越來越少

使用ipcs -m指令查看共享內存
使用ipcrm -m shmid指令刪除共享內存

函數刪除共享內存的方法
在這里插入圖片描述


4. 共享內存編碼實現

由于雙方進程編寫代碼有很多重復的地方
所以使用一個commom.h文件存放公共內容

commom.h文件中:

#pragma once
#include<iostream>
#include<string>
#include<unistd.h>
#include<cstdio>
#include<sys/shm.h>
#include<sys/ipc.h>
#include<sys/types.h>
#include<cassert>
#include<cstring>
#include<sys/stat.h>
#include<fcntl.h>
using namespace std;
#define PATHNAME "/home/kwy"  //形成key值的字符串
#define PROJ_ID 0x666  //形成key值的整數
#define SHM_SIZE 4096 //共享內存的大小最好是頁(PAGE : 4096)的整數倍

client端代碼:

#include"common.hpp"
int main()
{//獲取keykey_t k = ftok(PATHNAME, PROJ_ID);if (k < 0){perror("ftok");exit(1);}cout<<"creat key success: "<<k<<endl;// 獲取共享內存int shmid = shmget(k, SHM_SIZE, 0);if(shmid < 0){perror("shmget");exit(2);}cout<<"get shard success: "<<shmid<<endl;//掛接共享內存char *shmaddr = (char *)shmat(shmid, nullptr, 0);if(shmaddr == nullptr){perror("shmat");exit(3);}cout<<"attach success!"<<endl;//將共享內存看作數組,寫入數據char ch ='a';for(;ch<='z';ch++){snprintf(shmaddr,SHM_SIZE-1,"hello server,i am other proc,mypid: %d ,inc: %c",getpid(),ch);sleep(2);}// 去關聯int n = shmdt(shmaddr);assert(n != -1);cout<<"detach success!"<<endl;// client 要不要chmctl刪除呢?不需要!!return 0;
}

server端代碼:

#include"common.hpp"
int main()
{//創建公共的key的值key_t key = ftok(PATHNAME,PROJ_ID);cout<<"server key: "<<TransToHex(key)<<endl;assert(key!=-1);//創建共享內存(全新的共享內存)int shmid = shmget(key,SHM_SIZE,IPC_CREAT | IPC_EXCL | 0666);if(shmid==-1){perror("shmid");exit(1);}cout<<"creat shmid: "<<shmid<<endl;//將創建好的共享內容掛接到虛擬地址char* shmaddr = (char*)shmat(shmid,nullptr,0);//shmat的返回值是void*,與malloc相似要強轉cout<<"attach success!"<<endl;//使用共享內存,將共享內存當作一個大字符串//使用完共享內存后,將指定的內存與進程去關聯int n1 = shmdt(shmaddr);if(n1==-1)perror("shmdt");elsecout<<"detach success!"<<endl;//最后用代碼刪除共享內存int n2 = shmctl(shmid,IPC_RMID,nullptr);assert(n2!=-1);cout<<"delete shared memory: "<<shmid<<endl;return 0;
}

5. 進程互斥相關概念

大家在學習共享內存時有沒有發現一個問題:

假如共享區有一個變量a,client進程在將a進行++操作的同時,server進程將a的值從10改為了100,這里就會出現問題,已經被改為100的a值在client進程執行完操作后,會把在CPU中計算出來的11賦值給a,那么進程server就白修改了,這里顯然是有問題的

沒錯,在這個地方,共享內存被稱為共享資源,共享資源如果被同時訪問可能會出現某些預想不到的問題,所以各個進程不能在同一時間訪問共享資源,這種關系叫做進程互斥

在這里插入圖片描述

對于進程互斥和共享資源以及臨界區的認識遠遠沒有結束,今天我們只是窺見了冰山一角,在后續的學習中我們還會重點講這一個概念!


6. 總結

進程間通信的方式遠不止管道和共享內存這兩種,還有很經典的消息隊列以及信號量等方式這里并沒有過多講述,因為我們只是學習重點,并不是全部都要學會,但是學有余力的同學還是很有必要區了解一下的


🔎 下期預告:進程信號 🔍

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

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

相關文章

2024年2月23日 晨會匯報

Good morning, colleages! This is /?dɑ?.t?i/ speaking. As for my report today, I decide to wing it, so I didnt prepare a script. Now, Ill share an update about my recent work activities which encompasses two key area: a summary of my work yesterday a…

【Go channel如何控制goroutine并發執行順序?】

多個goroutine并發執行時&#xff0c;每一個goroutine搶到處理器的時間點不一致&#xff0c;gorouine的執行本身不能保證順序。即代碼中先寫的gorouine并不能保證先執行 思路&#xff1a;使用channel進行通信通知&#xff0c;用channel去傳遞信息&#xff0c;從而控制并發執行…

基于開源模型對文本和音頻進行情感分析

應用場景 從商品詳情頁爬取商品評論&#xff0c;對其做輿情分析&#xff1b;電話客服&#xff0c;對音頻進行分析&#xff0c;做輿情分析&#xff1b; 通過開發相應的服務接口&#xff0c;進一步工程化&#xff1b; 模型選用 文本&#xff0c;選用了通義實驗室fine-tune的st…

電腦錄屏軟件哪個好用?實測告訴你答案(2024年最新)

在當今信息化快速發展的時代&#xff0c;無論是錄制在線課程、游戲操作&#xff0c;還是制作教程、會議記錄&#xff0c;一款電腦錄屏軟件顯得尤為重要&#xff0c;可是電腦錄屏軟件哪個好用呢&#xff1f;本文將介紹三款主流的電腦錄屏軟件&#xff0c;通過分步驟詳細講述&…

使用maven集成spring在測試的時候報出了如下的異常:version 60

使用maven集成spring在測試的時候報出了如下的異常&#xff1a; Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 60 解決&#xff1a;

在word中將latex格式的公式轉化為帶有編號的mathtype公式

在word中將latex格式的公式轉化為帶有編號的mathtype公式 1.先在word里面配置好mathtype2.在word中設置mathtype的格式3.先將latex格式的公式轉化為mathml格式4.讀到這里&#xff0c;是不是覺得這個方法麻煩 1.先在word里面配置好mathtype 注意&#xff1a;1.word的版本應該是 …

基于springboot+vue的中小型醫院網站(前后端分離)

博主主頁&#xff1a;貓頭鷹源碼 博主簡介&#xff1a;Java領域優質創作者、CSDN博客專家、阿里云專家博主、公司架構師、全網粉絲5萬、專注Java技術領域和畢業設計項目實戰&#xff0c;歡迎高校老師\講師\同行交流合作 ?主要內容&#xff1a;畢業設計(Javaweb項目|小程序|Pyt…

Sovit3D數字孿生平臺 助力智慧海上風電場項目加速

我們常說地球是藍色星球&#xff0c;那是因為海洋約占地球面積的71%。如今&#xff0c;我國正在向“雙碳”目標不斷奮斗&#xff0c;海上風電也作為一種潛力清潔能源&#xff0c;迸發出前所未有的活力&#xff0c;海上吹來的風成為未來清潔能源新方向。 2024年海上風電項目加速…

Qt_快速安裝指南

下載Qt在線安裝程序&#xff08;不仔細介紹&#xff09;注冊Qt賬號&#xff08;不仔細介紹&#xff09;使用快速運行的命令&#xff0c;按照指定的下載地址下載 在Qt指定目錄打開cmd命令窗口.\eqt-unified-windows-x86-4.0.1-1-online. exe --mirror https://mirrors.ustc.edu.…

JVM虛擬機結構

虛擬機結構圖 從圖中看出&#xff1a; JVM虛擬機主要有三大部分組成&#xff1a; 1. 類加載器 2. JVM運行時內存 3. 執行引擎 一、類加載器 類加載器主要用來加載字節碼文件&#xff08;.class&#xff09;到內存中 二、內存結構 如圖&#xff1a;可將內存分為兩大部分&…

【go】IP相關工具類

文章目錄 1.判斷ipv4 or ipv62.計算cidr格式ip所含IP個數3.計算兩個ip區間所含ip個數 1.判斷ipv4 or ipv6 // return int 0:錯誤的ip 4:ipv4 6:ipv6 func CheckIp(ip string) int {if ip "" {return 4}out : net.ParseIP(ip)if out nil {return 0}if strings.Cont…

C1475D Cleaning the Phone 題解

文章目錄 C1475D Cleaning the Phone 題解Cleaning the Phone題面翻譯題目描述輸入格式輸出格式樣例 #1樣例輸入 #1樣例輸出 #1 提示算法&#xff1a;貪心代碼&#xff1a; C1475D Cleaning the Phone 題解 link Cleaning the Phone 題面翻譯 題目大意&#xff1a; 有 n …

【學習iOS高質量開發】——協議與分類

文章目錄 一、通過委托與數據源協議進行對象間通信1.委托模式2.要點 二、將類的實現代碼分散到便于管理的數個分類之中1.如何實現2.要點 三、總是為第三方類的分類名稱加前綴1.為什么總是為第三方類的分類名稱加前綴2.要點 三、勿在分類中聲明屬性1.勿在分類中聲明屬性的原因2.…

Android進階(二十九) 走近 IntentFilter

文章目錄 一、什么是IntentFilter &#xff1f;二、IntentFilter 如何過濾隱式意圖&#xff1f;2.1 動作測試2.2 類別測試2.3 數據測試 一、什么是IntentFilter &#xff1f; 如果一個 Intent 請求在一片數據上執行一個動作&#xff0c; Android 如何知道哪個應用程序&#xf…

網頁數據的解析提取(XPath的使用----lxml庫詳解)

在提取網頁信息時&#xff0c;最基礎的方法是使用正則表達式&#xff0c;但過程比較煩瑣且容易出錯。對于網頁節點來說&#xff0c;可以定義id、class或其他屬性&#xff0c;而且節點之間還有層次關系&#xff0c;在網頁中可以通過XPath或CSS選擇器來定位一個或多個節點。那么&…

Maven管理項目,本地倉庫有對應的jar包,但還是報找不到

文章目錄 業務場景錯誤提示分析過程解決辦法 業務場景 settings.xml種配置了私服&#xff0c;但是有些依賴私服上沒有&#xff0c;通過同事拷貝過來的。但是用maven打包時報紅了。 錯誤提示 Idea Maven錯誤&#xff1a;was cached in the local repository, resolution will…

RecycleView結合ItemTouchHelper實現拖動排序

最近項目中需要實現對某一類條目進行拖動排序功能&#xff0c;實現技術方案就是利用ItemTouchHelper綁定RecyclerView、ItemTouchHelper.Callback來實現UI更新&#xff0c;并且實現動態控制是否開啟拖動功能。其中&#xff0c;ItemTouchHelper是Google在androidx包中添加的&…

int128的實現(基本完成)

雖然有一個聲明叫_int128但是這并不是C標準&#xff1a; long long 不夠用&#xff1f;詳解 __int128 - FReQuenter - 博客園 (cnblogs.com) 網絡上去找int128的另類實現方法&#xff0c;發現幾乎都是在介紹_int128的 然后我就自己想了個辦法&#xff0c;當時還沒學C&#xf…

Spring Boot中實現列表數據導出為Excel文件

點擊下載《Spring Boot中實現列表數據導出為Excel文件》 1. 前言 本文將詳細介紹在Spring Boot框架中如何將列表數據導出為Excel文件。我們將通過Apache POI庫來實現這一功能&#xff0c;并解釋其背后的原理、提供完整的流程和步驟&#xff0c;以及帶有詳細注釋的代碼示例。最…

關于設備連接有人云的使用及modbus rtu協議,服務器端TCP調試設置

有人云調試 調試過程問題1. 關于modbus rtu協議,實質上有三種modbus基本原理modbus 格式2. 關于modbus crc16通信校驗3. 關于在ubuntu阿里云服務器端,監聽網絡數據之調試mNetAssist之前的一個項目,再拿出來回顧下。 調試過程 先 要在有人云,用手機號注冊一個服務賬號,官網顯…