Linux: shm_xx系列函數使用詳解

目錄

  • 一、shmget/shmctl/shmat/shmdt函數
    • 1、shmget
    • 2、shmctl
    • 3、shmat
    • 4、shmdt
    • 5、補充:ftok函數
    • 6、示例代碼
  • 二、shm_open/shm_unlink函數
    • 1、shm_open
    • 2、shm_unlink
    • 3、示例代碼
  • 三、課外閱讀

一、shmget/shmctl/shmat/shmdt函數

??shm_xx系列函數是用于操作共享內存的一組函數,它們通常包括shmget、shmctl、shmat和shmdt。下面對這些函數進行詳細解釋:

1、shmget

  • 功能:創建一個新的共享內存段或獲取一個已經存在的共享內存段的標識符。
  • 原型int shmget(key_t key, size_t size, int shmflg)
  • 參數
    • key:用于識別共享內存段的鍵值,通常使用 ftok 函數生成。
    • size:共享內存段的大小。單位是字節。
    • shmflg:打開標志,用于指定操作的方式,比如創建共享內存段、獲取共享內存標識符等。
  • 返回值:成功時返回共享內存段的標識符(非負整數),失敗時返回-1。
    shmget 函數是用于創建共享內存段、獲取共享內存標識符或者訪問一個已存在的共享內存段的函數,其聲明如下:

??shmget 函數的主要功能包括:

  • 如果指定的 key 對應的共享內存段不存在,并且設置了創建標志(IPC_CREAT),則會創建一個新的共享內存段,大小為 size 字節。
  • 如果指定的 key 對應的共享內存段存在,則會返回共享內存標識符。
  • 如果不希望創建共享內存段,可以不設置 IPC_CREAT 標志。此時若指定的 key 對應的共享內存段不存在,shmget 函數將會返回錯誤。

??shmget 函數的返回值是共享內存標識符(shmid),用于后續對共享內存段的訪問操作,比如連接共享內存、獲得共享內存的地址等。

??在使用 shmget 函數時,需要注意確保對共享內存的大小和權限的設置,避免潛在的問題,比如內存溢出或者權限不足等。同時,需要根據具體需求合理設置 shmflg 參數,確保對共享內存的訪問操作符合預期。

2、shmctl

  • 功能:用于控制共享內存段。
  • 原型int shmctl(int shmid, int cmd, struct shmid_ds *buf)
  • 參數
    • shmid:是共享內存標識符,是由 shmget 函數返回的。
    • cmd:是控制命令,用于指定對共享內存的具體操作,比如刪除共享內存段、獲取共享內存信息等。
    • buf:是指向 shmid_ds 結構體的指針,用于傳遞或者獲取共享內存的信息。
  • 返回值:成功時返回0,失敗時返回-1。
    shmctl 函數是用于控制共享內存段的操作函數,主要用于對共享內存段進行控制操作,比如刪除、獲取信息等,其聲明如下:

shmctl 函數的主要功能包括:

  • 獲取共享內存段的信息,比如共享內存大小、關聯進程數等。
  • 控制共享內存段的權限,比如修改共享內存的權限。
  • 刪除共享內存段。

cmd 參數可以取以下值之一:

  • IPC_STAT:獲取共享內存的狀態信息,并將其存儲在 buf 指向的結構體中。
  • IPC_SET:設置共享內存的狀態信息,更新共享內存的權限等。
  • IPC_RMID:刪除共享內存段,釋放資源。

??需要注意的是,在使用 shmctl 函數時,要根據具體需求選擇合適的控制命令,并確保傳入正確的參數,以免出現意外的錯誤。同時,刪除共享內存段時,需要注意確保所有關聯進程已經分離了共享內存段,否則刪除操作可能會失敗。

3、shmat

  • 功能:將共享內存段連接到調用進程的地址空間。
  • 原型void *shmat(int shmid, const void *shmaddr, int shmflg)
  • 參數
    • shmid:是共享內存標識符,是由 shmget 函數返回的。
    • shmaddr:是一個指針,用于指定將共享內存段映射到進程地址空間的地址,通常設為 NULL
    • shmflg:參數用于指定連接共享內存段的標志,通常可以設置為 0。
  • 返回值:成功時返回指向共享內存段起始地址的指針,失敗時返回-1。

??shmat 函數的主要作用是將共享內存段連接到當前進程的地址空間,實現進程對共享內存段的訪問。連接成功后,shmat 函數將返回一個指向共享內存段起始地址的指針,進程可以通過該指針來訪問共享內存段中的數據。

??一般情況下,shmaddr 參數設為 NULL,由系統自動選擇合適的地址來映射共享內存段到進程地址空間中。shmflg 參數通常設為 0,表示默認的連接標志,除非有特殊需求,一般不需要修改。

??需要注意的是,在使用 shmat 函數時,要確保傳入正確的共享內存標識符 shmid,避免出現連接錯誤。另外,在使用完共享內存后,要及時調用 shmdt 函數將共享內存段從當前進程地址空間中分離,避免資源泄漏。

4、shmdt

  • 功能:將共享內存段從調用進程的地址空間中分離。
  • 原型int shmdt(const void *shmaddr)
  • 參數
    • shmaddr:是共享內存段連接到進程地址空間的起始地址,通常是由 shmat 函數返回的。
  • 返回值:成功時返回0,失敗時返回-1。

??shmdt 函數的主要作用是斷開當前進程與共享內存段的連接,使得進程無法再訪問共享內存段中的數據。調用 shmdt 函數后,共享內存段仍然存在,但當前進程無法再對其進行操作。

??在使用 shmdt 函數時,需要傳入正確的共享內存段起始地址 shmaddr,確保將正確的共享內存段從當前進程中分離。另外,需要注意的是,分離共享內存段后,如果沒有其他進程仍然連接著該共享內存段,系統會釋放該共享內存段,從而釋放相關資源。

??在使用共享內存時,需要注意合理地管理共享內存的連接和分離,避免出現資源泄漏或者錯誤的操作。

ftok 函數是一個用于生成一個 System V IPC(Inter-Process Communication,進程間通信)鍵值的函數,其聲明如下:

5、補充:ftok函數

key_t ftok(const char *pathname, int proj_id);
  • pathname 參數是一個指向字符串的指針,用于指定一個已經存在的文件的路徑名。
  • proj_id 參數是一個用戶定義的整數,可以是 0 到 255 的范圍內的任意值。

??ftok 函數會根據指定的 pathnameproj_id 生成一個唯一的鍵值,用于創建或訪問 System V IPC 的資源,如共享內存、信號量和消息隊列。

??實際上,ftok 函數根據 pathname 參數對應文件的 inode 號和 proj_id 參數生成一個 32 位的鍵值,最高 8 位存放 proj_id,低 24 位存放 pathname 對應文件的 inode 號的后 24 位。這樣可以保證相同的 pathnameproj_id 參數生成相同的鍵值。

??需要注意的是,在使用 ftok 函數時要確保 pathname 參數是一個已經存在的文件的路徑名,否則會導致生成的鍵值不唯一。另外,proj_id 參數的取值范圍是 0 到 255,超出這個范圍可能導致鍵值重復。

??綜上所述,ftok 函數是用于生成 System V IPC 鍵值的一個實用工具函數,可以通過指定文件路徑和項目標識來確保生成唯一的鍵值,用于進程間通信的各種資源的創建和訪問。

6、示例代碼

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>#define SHM_SIZE 1024 // 共享內存大小int main() {key_t key = ftok("shmfile", 'R'); // 創建共享內存的鍵值int shmid;// 創建共享內存段shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);if (shmid == -1) {perror("shmget");exit(1);}// 連接共享內存段char *shmaddr = (char *)shmat(shmid, NULL, 0);if (shmaddr == (char *)-1) {perror("shmat");exit(1);}// 寫入數據到共享內存strcpy(shmaddr, "Hello, Shared Memory!");printf("Data written to shared memory: %s\n", shmaddr);// 分離共享內存段if (shmdt(shmaddr) == -1) {perror("shmdt");exit(1);}// 刪除共享內存段if (shmctl(shmid, IPC_RMID, 0) == -1) {perror("shmctl");exit(1);}return 0;
}

二、shm_open/shm_unlink函數

1、shm_open

??shm_open 是 POSIX 標準中定義的用于創建或打開共享內存對象的函數。與傳統的 shmget 函數類似,shm_open 提供了一種不同的方式來管理共享內存,使用文件描述符來標識共享內存對象。shm_open 的原型如下:

int shm_open(const char *name, int oflag, mode_t mode);
  • name 參數是一個指向表示共享內存對象名稱的字符串的指針。共享內存對象通過名稱在文件系統中標識。
  • oflag 參數指定了打開共享內存對象時的操作標志,可以是一組位或運算的標志,比如 O_CREAT(創建共享內存對象), O_RDWR(可讀寫方式打開)等。
  • mode 參數指定了新創建的共享內存對象的權限標志,通常與 open 系統調用中使用的 mode 參數一樣。

??使用 shm_open 函數創建或打開共享內存對象后,可以通過標準的文件 I/O 函數(如 readwrite)對共享內存進行讀寫操作。共享內存對象在文件系統中以名字為標識,不同進程可以通過相同的名字打開同一個共享內存對象,從而實現進程間通信。

??在使用 shm_open 函數時,需要注意以下幾點:

  • 共享內存對象的名稱必須在當前系統中是唯一的,以避免命名沖突。
  • 在打開共享內存對象后,應謹慎進行讀寫操作,避免發生競爭條件和數據一致性問題。
  • 當不再需要共享內存對象時,應當使用 shm_unlink 函數來釋放該共享內存對象,以防止資源泄漏。

??總的來說,shm_open 提供了一種基于文件描述符的共享內存對象管理方式,使得共享內存在不同進程之間的使用更加靈活和方便。

2、shm_unlink

??shm_unlink 是一個函數,用于刪除由 shm_open 創建的共享內存對象的名稱。在 POSIX 標準中,共享內存對象在文件系統中以名稱標識,使用 shm_open 打開該共享內存對象后,可以通過 shm_unlink 函數刪除該對象的名字,但不會立即釋放共享內存本身。只有在所有進程都關閉該共享內存對象的文件描述符或調用 shm_unlink 之后,共享內存對象才會被徹底刪除。shm_unlink 的原型如下:

int shm_unlink(const char *name);
  • name 參數是一個指向表示要刪除的共享內存對象名稱的字符串的指針。

??使用 shm_unlink 函數可以確保在不再需要共享內存對象時清理對象的名稱,這樣可以避免其他進程再次通過該名稱打開共享內存對象。但需要注意的是,即使調用了 shm_unlink,只有當所有打開該共享內存對象的文件描述符都關閉,共享內存對象才會被系統真正刪除。

??一般來說,在不再需要使用共享內存對象時,建議及時調用 shm_unlink,以便及時釋放已不需要的資源。這樣可以更好地管理共享內存,避免資源泄漏和冗余共享內存對象的存在。

3、示例代碼

??以下是一個簡單的示例代碼,展示了如何使用 shm_openshm_unlink 函數來創建和刪除共享內存對象的名稱。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>#define SHM_NAME "/my_shared_memory"
#define SHM_SIZE 1024int main() {const char *data = "Hello, this is shared memory demo!";// Create or open a shared memory objectint shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);ftruncate(shm_fd, SHM_SIZE);// Map the shared memory object into memorychar *shm_ptr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);// Write data to the shared memorystrcpy(shm_ptr, data);printf("Data written to shared memory: %s\n", shm_ptr);// Unmap the shared memorymunmap(shm_ptr, SHM_SIZE);// Close the shared memory objectclose(shm_fd);// Unlink the shared memory object nameshm_unlink(SHM_NAME);return 0;
}

??在這個示例代碼中,首先使用 shm_open 函數創建或打開一個共享內存對象,并指定名稱為 "/my_shared_memory"。然后使用 ftruncate 函數設置共享內存對象的大小為 SHM_SIZE 字節。

??接著,使用 mmap 函數將共享內存對象映射到當前進程的內存空間中,使得可以對其進行讀寫操作。將數據寫入共享內存后,通過 munmap 函數解除共享內存的映射,并通過 close 函數關閉共享內存對象的文件描述符。

??最后,調用 shm_unlink 函數刪除共享內存的名稱,這樣其他進程就無法再使用該名稱打開共享內存對象。

三、課外閱讀

推薦閱讀:進程間通信–共享內存篇

??歡迎大家指導和交流!如果我有任何錯誤或遺漏,請立即指正,我愿意學習改進。期待與大家一起進步!

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

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

相關文章

SpringBoot整合JdbcTemplate

?作者簡介:大家好,我是Leo,熱愛Java后端開發者,一個想要與大家共同進步的男人???? ??個人主頁:Leo的博客 ??當前專欄: 循序漸進學SpringBoot ?特色專欄: MySQL學習 ??本文內容:SpringBoot整合JdbcTemplate ??個人知識庫: Leo知識庫,歡迎大家訪問 目錄 …

設置文字之間的間距應該如何實現

設置文字之間的間距&#xff0c;通常指的是字母之間&#xff08;字符間距&#xff09;或單詞之間的間距。在CSS中&#xff0c;這可以通過letter-spacing和word-spacing屬性來實現。 字符間距&#xff08;letter-spacing&#xff09; letter-spacing屬性用于調整字符之間的間距…

【Git學習筆記】提交PR

step1 克隆一個倉庫 git clone .....step2 創建一個分支 (Creating a branch) # 創建并切換到本地新分支&#xff0c;分支的命名盡量簡潔&#xff0c;并與解決的問題相關 git checkout -b delete-unused-linkstep3 做出修改 (Make changes) step4 提交修改 # 保存本地修…

DDR5內存相比DDR4內存的優勢和區別?選擇哪一個服務器內存配置能避免丟包和延遲高?

根據幻獸帕魯服務器的實際案例分析&#xff0c;選擇合適的DDR4與DDR5內存大小以避免丟包和延遲高&#xff0c;需要考慮以下幾個方面&#xff1a; 性能與延遲&#xff1a;DDR5內存相比DDR4在傳輸速率、帶寬、工作電壓等方面都有顯著提升&#xff0c;但同時也伴隨著更高的延遲。D…

PostgreSQL開發與實戰(4)查詢性能Top SQL

作者&#xff1a;太陽 一、查詢當前正在運行的Top SQL 查詢當前正在運行的會話中耗時最長的Top SQL&#xff0c;where條件可按需修改SELECT pgsa.datname AS database_name, pgsa.usename AS user_name, pgsa.client_addr AS client_addr, pgsa.application_name AS applicat…

你知道什么是回調函數嗎?

c語言中的小小白-CSDN博客c語言中的小小白關注算法,c,c語言,貪心算法,鏈表,mysql,動態規劃,后端,線性回歸,數據結構,排序算法領域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 給大家分享一句我很喜歡我話&#xff1a; 知不足而奮進&#xff0c;望遠山而前行&am…

Unity3D外包 北京動點軟件:基于U3D開發自動駕駛技術分析

在Unity3D中開發自動駕駛AI是一個充滿挑戰和潛力的領域。以下是一些關鍵步驟和考慮因素&#xff1a; 來百度APP暢享高清圖片 1. 創建虛擬環境&#xff1a; 使用Unity3D創建一個逼真的虛擬環境&#xff0c;模擬現實世界的道路、交通標志、車輛和障礙物等。 確保場景具有真實的…

4款免費且實用的.NET反編譯工具

.NET 反編譯工具的作用 .NET反編譯工具能夠將已經編譯好的.NET程序集轉換為易于理解的源代碼&#xff0c;它們可以幫助開發人員恢復丟失的源代碼、理解和分析第三方組件dll、學習其他人的代碼、更好的查找修復 bug 或進行逆向工程等&#xff08;注意&#xff1a;請在法律允許范…

【C++ 標準流,文件流】

C 標準流&#xff0c;文件流 ■ 標準輸入&#xff0c;輸出流&#xff0c;■ 文件流&#xff08;ofstream寫入&#xff0c;ifstream讀取&#xff0c;fstream創建-寫入-讀取&#xff09;■ open()■ ofstream■ ifstream■ 流插入<<■ 文件位置指針 ■ 標準輸入&#xff0c…

SpringBoot系列(一):SpringBoot介紹

SpringBoot系列(一)&#xff1a;SpringBoot介紹 1. SpringBoot介紹 SpringBoot是由Pivotal團隊提供的一套用于構建微服務的基礎框架&#xff0c;它旨在簡化Spring應用程序的創建和開發過程。 SpringBoot通過設計大量的自動化配置等方式來簡化Spring原有樣板化的配置&#xff…

用Visual Studio 2015成功編譯、發布UMDF驅動到目標機!!

開發工具&#xff1a;Visual Studio 2015企業版 主 機&#xff1a;windows10 X64企業版&#xff0c;主機是安裝了Visual Studio 2015的操作系統&#xff0c;主要進行驅動開發和調試。 目 標 機&#xff1a;windows10 X86企業版&#xff0c;目標機是安裝和調試驅動的操作…

阿里巴巴面試必備:數據庫集群知識全面解讀!

大家好,我是小米。今天,我們將深入探討阿里巴巴面試題中一個備受關注的話題:數據庫集群。作為技術領域中的一項重要實踐,數據庫集群不僅是企業架構中的核心組成部分,更是保障系統穩定性和數據可靠性的關鍵一環。讓我們一起來揭秘數據庫集群的奧秘吧! 主從復制過程 主從…

文件操作(超詳細版本)

本章重點 為什么使用文件什么是文件文件的打開和關閉文件的順序讀寫文件的隨機讀寫文件讀取結束的判定 為什么使用文件 我們前面學習結構體時&#xff0c;寫通訊錄的程序&#xff0c;當通訊錄運行起來的時候&#xff0c;可以給通訊錄中增加、刪除數 據&#xff0c;此時數據是…

手勢識別應用介紹

目錄 一、功能介紹 二、安裝部署說明 2.1 文件目錄說明 2.2 手勢識別部分 一、功能介紹 這是一個通過攝像頭捕獲手勢&#xff0c;根據不同的手勢來做出不同操作的計算機程序。目前可以識別9種手勢&#xff0c;可以根據識別到的手勢&#xff0c;進行打開應用、增大音量、減小音量…

[AIGC] 請舉例說明在運行時讀取注解的應用場景。

很高興你對于在運行時讀取注解的應用場景感興趣。以下是我為你整理的一些典型場景&#xff1a; 1. Spring框架 Spring框架廣泛地使用了運行時注解。例如Autowired注解&#xff0c;它可以在運行時實現依賴注入的功能。Spring在啟動時&#xff0c;會通過反射機制尋找到被Autowi…

mkfs.ext4 --- 對磁盤設備進行Ext4格式化

mkfs.ext4命令來自于英文詞組“make filesystem Ext4”的縮寫&#xff0c;其功能是用于對磁盤設備進行Ext4格式化的操作。 mkfs.ext4 參數-b block-size 塊大小&#xff08;1k,2k,4k&#xff09; -c 壞塊測試 -l filename從文件讀壞塊列表 -C cluster-size 簇大小 (大塊分配持性…

交友社交軟件開發-php交友聊天系統-

為了開發一個高效的交友系統&#xff0c;需要一個完善的信息管理和篩選機制。這個系統應該能夠根據用戶的個人信息、興趣愛好、價值觀等標準進行篩選&#xff0c;并向用戶提供符合他們要求心儀的人的信息。為了實現這個目標&#xff0c;系統可以利用人工智能技術&#xff0c;分…

MySQL基礎-----SQL語句之DDL語句

目錄 前言 開啟登錄數據庫 一、數據庫操作 1.查詢所有數據庫 2.切換使用數據庫 3.查詢當前使用的數據庫 4.創建數據庫 創建一個hello數據庫, 使用數據庫默認的字符集。 創建一個itheima數據庫&#xff0c;并且指定字符集 5.刪除數據庫 二、表操作 1.查詢當前數據庫所有…

JAVA的學習日記

JAVA的學習日記&#xff08;2024.3.1&#xff09;&#xff08;b站韓順平老師課程學習筆記版&#xff09; ps:撿起忘光光的Java語言 Sublime //1. public是公有&#xff0c;class是類 //2. public class Hello表示Hello是一個類&#xff0c;是一個public公有的類 //3. Hello{…

解決Unable to load class ‘org.gradle.api.attributes.VerificationType‘

在使用AdnroidStudio開發過程中難免會遇到Unable to load class org.gradle.api.attributes.VerificationType報錯&#xff0c;可以嘗試清理緩存重啟解決 打開 File-》Invalidate Caches... 重啟AndroidStudio后&#xff0c;重新加載即可&#xff0c;但也不是百分百解決。