共享內存原理介紹及簡單使用

每當我們執行一個程序時,對于操作系統來講就創建了一個進程,在這個過程中,伴隨著資源的分配和釋放。可以認為進程是一個程序的一次執行過程。進程的內存空間是相互獨立的,一般而言是不能相互訪問的。但很多情況下進程間需要互相通信,來完成系統的某項功能。進程通過與內核及其它進程之間的互相通信來協調它們的行為。進程間通信的方式通常由以下幾種:

管道分為有名管道和無名管道。無名管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程間使用.進程的親緣關系一般指的是父子關系。無明管道一般用于兩個不同進程之間的通信。當一個進程創建了一個管道,并調用fork創建自己的一個子進程后,父進程關閉讀管道端,子進程關閉寫管道端,這樣提供了兩個進程之間數據流動的一種方式。有名管道也是一種半雙工的通信方式,但是它允許無親緣關系進程間的通信。

信號量是一個計數器,可以用來控制多個線程對共享資源的訪問.,它不是用于交換大批數據,而用于多線程之間的同步.它常作為一種鎖機制,防止某進程在訪問資源時其它進程也訪問該資源.因此,主要作為進程間以及同一個進程內不同線程之間的同步手段.Linux提供了一組精心設計的信號量接口來對信號進行操作,它們不只是針對二進制信號量,下面將會對這些函數進行介紹,但請注意,這些函數都是用來對成組的信號量值進行操作的。它們聲明在頭文件sys/sem.h中。

信號是一種比較復雜的信方式,用于通知接收進程某個事件已經發生。

消息隊列是消息的鏈表,存放在內核中并由消息隊列標識符標識.消息隊列克服了信號傳遞信息少,管道只能承載無格式字節流以及緩沖區大小受限等特點.消息隊列是UNIX下不同進程之間可實現共享資源的一種機制,UNIX允許不同進程將格式化的數據流以消息隊列形式發送給任意進程.對消息隊列具有操作權限的進程都可以使用msget完成對消息隊列的操作控制.通過使用消息類型,進程可以按任何順序讀信息,或為消息安排優先級順序。

socket,即套接字是一種通信機制,憑借這種機制,客戶/服務器(即要進行通信的進程)系統的開發工作既可以在本地單機上進行,也可以跨網絡進行。也就是說它可以讓不在同一臺計算機但通過網絡連接計算機上的進程進行通信。也因為這樣,套接字明確地將客戶端和服務器區分開來。

共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問.共享內存是最快的IPC(進程間通信)方式,它是針對其它進程間通信方式運行效率低而專門設計的.它往往與其他通信機制,如信號量,配合使用,來實現進程間的同步與通信。

本文主要介紹共享內存的通信方式

  • 共享內存概念

在Linux系統中,每個進程都有獨立的虛擬內存空間,也就是說不同的進程訪問同一段虛擬內存地址所得到的數據是不一樣的,這是因為不同進程相同的虛擬內存地址會映射到不同的物理內存地址上。但有時候為了讓不同進程之間進行通信,需要讓不同進程共享相同的物理內存,Linux通過 共享內存 來實現這個功能。

共享內存就是允許兩個或多個進程共享一定的存儲區。就如同 malloc() 函數向不同進程返回了指向同一個物理內存區域的指針。當一個進程改變了這塊地址中的內容的時候,其它進程都會察覺到這個更改。因為數據不需要在客戶機和服務器端之間復制,數據直接寫到內存,不用若干次數據拷貝,所以這是最快的一種通信方式。

  • 共享內存的簡單使用
  1. 獲取共享內存

要使用共享內存,首先需要使用 shmget() 函數獲取共享內存,shmget() 函數的聲明如下:int shmget(key_t key, size_t size, int shmflg);

參數 key 一般由 ftok() 函數生成,用于標識系統的唯一IPC資源。

參數 size 指定創建的共享內存大小。

參數 shmflg 指定 shmget() 函數的動作,比如傳入 IPC_CREAT 表示要創建新的共享內存。

函數調用成功時返回一個新建或已經存在的的共享內存標識符,取決于shmflg的參數。失敗返回-1,并設置錯誤碼。

  1. 關聯共享內存

shmget() 函數返回的是一個標識符,而不是可用的內存地址,所以還需要調用 shmat() 函數把共享內存關聯到某個虛擬內存地址上。shmat() 函數的聲明如下:void *shmat(int shmid, const void *shmaddr, int shmflg);

參數 shmid 是 shmget() 函數返回的標識符。

參數 shmaddr 是要關聯的虛擬內存地址,如果傳入0,表示由系統自動選擇合適的虛擬內存地址。

參數 shmflg 若指定了 SHM_RDONLY 位,則以只讀方式連接此段,否則以讀寫方式連接此段。

函數調用成功返回一個可用的指針(虛擬內存地址),出錯返回-1

  1. 取消關聯共享內存

當一個進程不需要共享內存的時候,就需要取消共享內存與虛擬內存地址的關聯。取消關聯共享內存通過 shmdt() 函數實現,聲明如下:int shmdt(const void *shmaddr);

參數 shmaddr 是要取消關聯的虛擬內存地址,也就是 shmat() 函數返回的值。

函數調用成功返回0,出錯返回-1。

  1. 刪除共享內存

當一個共享內存不再使用時,就需要刪除它,刪除共享內存的函數聲明如下:int shmctl(int shm_id, int command, struct shmid_ds *buf);

參數shm_id是shmget函數返回的共享內存標識符。

參數command填IPC_RMID。

參數buf填0。

5、使用舉例

下面通過一個例子來介紹一下共享內存的使用方法。在這個例子中,有兩個進程,分別為 進程A 和 進程B,進程A 創建一塊共享內存,然后寫入數據,進程B 獲取這塊共享內存并且讀取其內容。

進程A代碼內容:

#include <stdio.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#define SHM_PATH "/tmp/shm"

#define SHM_SIZE 128

int main(int argc, char *argv[])

{

??? int shmid;

??? char *addr;

??? key_t key = ftok(SHM_PATH, 0x6666);

??? shmid = shmget(key, SHM_SIZE, IPC_CREAT|IPC_EXCL|0666);

??? if (shmid < 0) {

??????? printf("failed to create share memory\n");

??????? return -1;

??? }

??? addr = shmat(shmid, NULL, 0);

??? if (addr <= 0) {

??????? printf("failed to map share memory\n");

??????? return -1;

??? }

??? sprintf(addr, "%s", "Hello World\n");

??? return 0;

}

進程B代碼內容:

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#define SHM_PATH "/tmp/shm"

#define SHM_SIZE 128

int main(int argc, char *argv[])

{

??? int shmid;

??? char *addr;

??? key_t key = ftok(SHM_PATH, 0x6666);

??? char buf[128];

??? shmid = shmget(key, SHM_SIZE, IPC_CREAT);

??? if (shmid < 0) {

??????? printf("failed to get share memory\n");

??????? return -1;

??? }

??? addr = shmat(shmid, NULL, 0);

??? if (addr <= 0) {

??????? printf("failed to map share memory\n");

??????? return -1;

??? }

??? strncpy(buf, addr, 128);

??? printf("%s", buf);

??? return 0;

}

使用gcc編譯,gcc -o A.out A.c ,gcc -o B.out B.c 。編譯完成后,測試時先運行進程A,然后再運行進程B,可以看到進程B會打印出 “Hello World”,說明共享內存已經創建成功并且讀取。

  • 使用共享內存的優缺點
  1. 優點

我們可以看到使用共享內存進行進程間的通信真的是非常方便,而且函數的接口也簡單,數據的共享還使進程間的數據不用傳送,而是直接訪問內存,也加快了程序的效率。同時,它也不像匿名管道那樣要求通信的進程有一定的父子關系。

  1. 缺點

共享內存沒有提供同步的機制,這使得我們在使用共享內存進行進程間通信時,往往要借助其他的手段來進行進程間的同步工作。

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

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

相關文章

上海泗博MODBUS轉PROFINET網關TS-180 網關連接LED顯示屏應用案例

項目 常州某鋼鐵公司的軋鋼車間為了更清晰地顯示當天軋鋼系統各環節的工作參數&#xff0c;如軋鋼的日期、鋼種、吐絲機設備運行情況等&#xff0c;引進了另一家為其定制的LED顯示屏。軋鋼系統各環節的設備參數通過西門子S7-1500PLC采集后&#xff0c;實時顯示在LED顯示屏上&am…

飛瓜數據B站丨B站UP主11月第3周榜單排行榜榜單(B站平臺)發布!

飛瓜輕數發布2023年11月13日-11月19日飛瓜數據UP主排行榜&#xff08;B站平臺&#xff09;&#xff0c;通過充電數、漲粉數、成長指數、帶貨數據等維度來體現UP主賬號成長的情況&#xff0c;為用戶提供B站號綜合價值的數據參考&#xff0c;根據UP主成長情況用戶能夠快速找到運營…

Linux網絡——傳輸層

目錄 一.再談端口概念 二.UDP協議 1.UDP協議格式 2.UDP的特點 3.面向數據報 4.UDP的緩沖區 5.UDP使用注意事項 6.UDP協議在內核中的表現形式 7.基于UDP的應用層協議 三.TCP協議 1.TCP協議格式 2.TCP確認應答機制 3.超時重傳機制 4.TCP報文六位標志位 5.滑動窗口 6…

制作抖音查券返利機器人的簡易步驟

制作抖音查券返利機器人的簡易步驟 隨著社交電商的快速發展&#xff0c;越來越多的消費者開始通過優惠券和返利來省錢購物。而抖音作為一款廣受歡迎的短視頻平臺&#xff0c;也為消費者提供了一個全新的購物體驗。本文將結合微賺淘客系統&#xff0c;介紹如何制作一個簡易的抖…

Web3與Web3.0: Web3指的是去中心化和基于區塊鏈的網絡,Web3.0指的是鏈接或語義網絡。

目錄 Web3與Web3.0: Web3指的是去中心化和基于區塊鏈的網絡 Web3.0指的是鏈接或語義網絡。

Flutter開發實踐:用一套代碼構建多端精美應用

&#x1f3c6;作者簡介&#xff0c;黑夜開發者&#xff0c;CSDN領軍人物&#xff0c;全棧領域優質創作者?&#xff0c;CSDN博客專家&#xff0c;阿里云社區專家博主&#xff0c;2023年6月CSDN上海賽道top4。 &#x1f3c6;數年電商行業從業經驗&#xff0c;歷任核心研發工程師…

Python下使用requests庫遇到的問題及解決方案

每一盞燈都有一個故事……當凌晨2點我的房間燈還亮著時&#xff0c;那就是我與BUG的一場生死博弈。一個人靜靜地坐在電腦前不斷地寫代碼&#xff0c;感覺快要麻木了&#xff0c;好比閉關修煉一樣枯燥無味。最終當我打通任督二脈后&#xff0c;bug修復迎來的一片曙光。 一、問題…

clang+llvm多進程gdb調試

clangllvm多進程gdb調試 前言1. 命令行gdb2. 父進程調試3. 子進程調試4. 返回父進程 前言 在學習新增llvm的優化pass時&#xff0c;需要跟蹤clang及llvm的調用棧。然而llvm通過posix_spawn()創建了新進程&#xff0c;這使得gdb調試必須有一定的技巧了。 1. 命令行gdb 以下命…

函數式編程-Stream流筆記-三更草堂

函數式編程-Stream流 1. 概述 1.1 為什么學&#xff1f; 能夠看懂公司里的代碼 大數量下處理集合效率高 代碼可讀性高 消滅嵌套地獄 //查詢未成年作家的評分在70以上的書籍 由于數據中作家和書籍可能出現重復&#xff0c;需要進行去重 List<Book> bookList new Ar…

4G5G智能執法記錄儀在保險公司車輛保險遠程定損中的應用

4G智能執法記錄儀&#xff1a;汽車保險定損的**利器 隨著科技的不斷進步&#xff0c;越來越多的智能設備應用到日常生活中。而在車輛保險定損領域&#xff0c;4G智能執法記錄儀的出現無疑是一大**。它不僅可以實現遠程定損&#xff0c;還能實現可視化操作、打印保單以及數據融…

WCF Demo

1.WCF概述 WCF是用于構建分布式應用程序和服務的框架。它提供了用于創建和管理分布式系統的工具和庫&#xff0c;支持多種通信協議和傳輸方式&#xff0c;如HTTP、TCP、Named Pipes等。WCF基于服務的概念&#xff0c;允許開發人員定義服務契約、實現服務邏輯&#xff0c;并通過…

給定一個非嚴格遞增排列的有序數組,刪除數組中的重復項

實例要求&#xff1a;1、給定一個非嚴格遞增排列的有序數組 nums &#xff1b;2、原地 刪除重復出現的元素&#xff0c;使每個元素 只出現一次 &#xff1b;3、返回刪除后數組的新長度&#xff1b;4、元素的 相對順序 應該保持 一致 &#xff1b;5、然后返回 nums 中唯一元素的…

dolphinscheduler有任務一直在運行(問題)目前對數據庫解決

dolphinscheduler有任務一直在運行&#xff08;問題&#xff09;目前對數據庫解決 危害&#xff1a; 這么多的任務沒有結束&#xff0c;會涉及很多問題的&#xff0c;系統的數據盤會不斷入職日志&#xff0c;數據量很大&#xff0c; 其實對于dolphinscheduler的性能是下降的&a…

WMware虛擬機與主機互相共享文件安裝VMware Tools灰色無法點擊安裝解決方案

一、背景 虛擬機與主機互傳文件最簡單的方法&#xff0c;就是給虛擬機系統安裝VMware Tools。 安裝VMware Tools后虛擬機系統和主機的文件可以相互拖拽&#xff0c;文字也可以任意粘貼復制。 二、遇到的問題 使用VMware時&#xff0c;安裝VMware Tools或者重新安裝VMware To…

假期對企業郵箱的維護和管理策略

假期應該對企業郵箱做些什么&#xff1f;放假后對企業郵箱的自動回復設置將在這里單獨列出。自動回復是你與新老客戶溝通的橋梁。告訴老客戶你放假了&#xff0c;但你會花時間回復他。還告訴新客戶&#xff08;新詢價客戶&#xff09;你在假期不能及時回復他&#xff0c;他們會…

m4s格式視頻文件如何轉mp4?三個方法教會你!

m4s格式是一種視頻分片格式&#xff0c;它將視頻文件分成多個小塊&#xff0c;方便網絡傳輸和播放。這種格式常用于流媒體服務&#xff0c;如在線視頻網站、直播平臺等&#xff0c;比如B站嗶哩嗶哩下載下來的視頻就是這種格式。 方法一&#xff1a;野蔥視頻轉換器 一款音視頻轉…

鋸木棍

題目描述 有一根粗細均勻長度為 L 的木棍&#xff0c;先用紅顏色刻度線將它 m 等分&#xff0c;再用藍色刻度線將 其 n 等分&#xff08; m>n &#xff09;&#xff0c;然后按所有刻度線將該木棍鋸成小段&#xff0c;計算并輸出長度最長的木棍的長度和根數。 輸入格式…

【Python】數據類型和切片的零碎知識點

1. 數據類型 pow(a, b, c) # a^b % c print("happy {}".format(name))數字類型包括整數&#xff0c;浮點數&#xff0c;復數 0x9a表示十六進制數&#xff08;0x&#xff0c;0X開頭表示十六進制&#xff09; 0b1010&#xff0c;-0B101表示二進制數&#xff08;0…

python基礎-numpy

numpy中shape (1,X) 和 &#xff08;X&#xff0c;&#xff09;的區別 參考 首先放結論&#xff1a;shape(x,)是一維數組&#xff0c;ndim1,[1,2,3,…x] ;shape(1,x)是二維&#xff1f;數組&#xff0c;ndim2,[[1,2,3,…n]] 由于array.shape 表示數組的維度&#xff0c;返回一…

【Linux】權限的理解和使用

&#x1f466;個人主頁&#xff1a;Weraphael ?&#x1f3fb;作者簡介&#xff1a;目前正在學習c和算法 ??專欄&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起進步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指點一二 如果文章對…