日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux进程间通信一 System V 共享内存简介与示例

發(fā)布時間:2025/4/5 linux 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux进程间通信一 System V 共享内存简介与示例 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

1. System V共享內(nèi)存簡介

2. API介紹

2.0 key_t和標(biāo)識符

2.1? 創(chuàng)建system v共享內(nèi)存

2.2 映射共享內(nèi)存并使用

2.3?取消共享內(nèi)存映射

2.4?控制共享內(nèi)存

3. 實例

3.1 共享內(nèi)存寫示例

3.2 共享內(nèi)存讀示例

4. 運行

5.?注意事項

6. 參考資料


1. System V共享內(nèi)存簡介

System V IPC通常指的是以下三種:

  • System V 消息隊列(message queues)
  • System V 信號量(semaphores)
  • System V 共享內(nèi)存(shared memory)
  • System V IPC最早是在上世紀(jì)70年代末由貝爾實驗室開發(fā)出來,三種IPC在實現(xiàn)架構(gòu)、使用方式上有很多相同之處,比如內(nèi)核實現(xiàn)里共用了ipc_perm權(quán)限管理結(jié)構(gòu)體,使用方式上都包括基本的xxxget,xxxctl等等。今天主要介紹下System V 共享內(nèi)存的使用方式。共享內(nèi)存作為IPC通信中最快的一種,之所以快是因為一旦創(chuàng)建成功,后續(xù)操作無需內(nèi)核拷貝數(shù)據(jù)以及系統(tǒng)調(diào)用,通信雙方可以直接操作共享內(nèi)存來通信。因為開發(fā)出來比較早,所以存在一些缺陷,所以就有了Posix IPC的產(chǎn)生,不過這是后話,在此不提。首先看下共享內(nèi)存的接口。

    2. API介紹

    2.0 key_t和標(biāo)識符

    System V IPC對象通過標(biāo)識符來區(qū)分,該標(biāo)志符具有系統(tǒng)唯一性,是操作系統(tǒng)內(nèi)的全局變量。生成SystemV IPC對象的Get函數(shù)需要一個key_t參數(shù),這是一個整型變量,用于對應(yīng)一個標(biāo)識符。該標(biāo)識符通常有三種方法生成:

  • 使用隨機(jī)固定值
  • 使用IPC_PRIVATE,這表示每次生成IPC對象的時候都會創(chuàng)建一個新的標(biāo)識符,因此不相干的進(jìn)程之間無法知道標(biāo)識符ID,因此通常只用于父子進(jìn)程,子進(jìn)程繼承父進(jìn)程的IPC標(biāo)識符,因而可以通信。
  • 使用ftok函數(shù)生成key_t,該函數(shù)組合路徑的屬性和傳入的proj_id拼出一個key_t,實際使用的時候路徑通常都是可執(zhí)行文件路徑。
  • #include <sys/types.h> #include <sys/ipc.h>/** * @brief 根據(jù)路徑屬性和proj_id創(chuàng)建key_t * * @params pathname 路徑名,文件必須存在且可訪問 * @params proj_id 自定義ID,只使用低8位(不能為0) * * @returns 成功返回key_t,失敗返回-1 */key_t ftok(const char *pathname, int proj_id);

    ?

    2.1? 創(chuàng)建system v共享內(nèi)存

    可以使用ipcs | ipcrm | ipcmk 查看、刪除和創(chuàng)建共享內(nèi)存

    #include <sys/ipc.h> #include <sys/shm.h>/** * @brief 創(chuàng)建共享內(nèi)存ID * * @params key 與shm_id關(guān)聯(lián)的key,三種生成方式,包括IPC_PRIVATE,注意key和shm_id不是綁定關(guān)系,相同的key產(chǎn)生的標(biāo)識符不一定相同。 * @params size 共享內(nèi)存的大小,必須是正整數(shù)。 * @params shmflg 標(biāo)志位和權(quán)限控制標(biāo)志位,可以多個用or運算。IPC_CREAT、 IPC_EXCL * * @returns 成功返回shmid,失敗返回-1 */int shmget(key_t key, size_t size, int shmflg);

    根據(jù)標(biāo)志位的不同,有如下幾種情況:

    oflag參數(shù)key不存在key已經(jīng)存在
    無特殊標(biāo)志位返回-1返回標(biāo)識符
    IPC_CREAT返回新建標(biāo)識符返回已有標(biāo)識符
    IPC_CREAT|IPC_EXCL返回新建標(biāo)識符返回-1

    ?

    2.2 映射共享內(nèi)存并使用

    使用共享內(nèi)存前需要將其映射到經(jīng)常自身地址空間,之后就可以像malloc分配的內(nèi)存一樣使用了

    #include <sys/types.h> #include <sys/shm.h>/** * @brief 映射共享內(nèi)存到進(jìn)程指定地址 * * @params shmid 共享內(nèi)存標(biāo)識符 * @params shmaddr 映射的地址,為NULL則內(nèi)核自動選擇合適的地址,非空并且設(shè)置SHM_RND標(biāo)志位,則自動對齊,如果沒有此標(biāo)志位并且不對齊,報錯。 * @params shmflg 可以設(shè)置SHM_RND、SHM_REMAP,SHM_RDONLY * 如果映射的地址已經(jīng)有了映射,可以設(shè)置SHM_REMAP標(biāo)志位重新映射,否則報錯。 * 如果地址不對齊,可以設(shè)置SHM_RND標(biāo)志位,此時內(nèi)核自動找到符合符合要求的地址,否則報錯。 * * @returns 成功返回映射地址,可以像malloc返回的地址那樣操作,失敗返回 (void *) -1 */void *shmat(int shmid, const void *shmaddr,int shmflg);

    2.3?取消共享內(nèi)存映射

    #include <sys/types.h> #include <sys/shm.h>/** * @brief 取消共享內(nèi)存映射 * * @params shmaddr shmat返回的共享內(nèi)存地址 * * 只是減少共享內(nèi)存的引用計數(shù)并未實際刪除共享內(nèi)存 * * @returns 成功返回0,失敗返回 -1 */int shmdt(const void *shmaddr);

    2.4?控制共享內(nèi)存

    #include <sys/ipc.h> #include <sys/shm.h>struct shmid_ds {struct ipc_perm shm_perm; /* 所有權(quán)及權(quán)限 */size_t shm_segsz; /* 共享內(nèi)存大小 (bytes) */time_t shm_atime; /* 上次shmat時間 */time_t shm_dtime; /* 上次shmdt時間 */time_t shm_ctime; /* 上次修改時間 */pid_t shm_cpid; /* 創(chuàng)建進(jìn)程皮帶 */pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */shmatt_t shm_nattch; /* 當(dāng)前shmat進(jìn)程數(shù)量 */... };/** * @brief 取消共享內(nèi)存映射 * * @params shmid 共享內(nèi)存標(biāo)識符 * @params cmd 控制命令,IPC_STAT, IPC_SET, IPC_RMID, SHM_LOCK, SHM_UNLOCK * @params buf 緩存 * IPC_STAT 獲取對應(yīng)共享內(nèi)存信息,存到buf緩存里。 * IPC_SET 只能修改shm_perm里面的uid,gid及mode * IPC_RMID 刪除共享內(nèi)存,只有引用計數(shù)為0才真正刪除 * SHM_LOCK 阻止共享內(nèi)存被替換出去 * SHM_UNLOCK 和SHM_LOCK相反 * * @returns 成功返回0,失敗返回 -1 */int shmctl(int shmid, int cmd, struct shmid_ds *buf);

    3. 實例

    3.1 共享內(nèi)存寫示例

    /* ** Name: shm_write.c ** Desc: 共享內(nèi)存寫端 ** Author: masonf ** Date: 2020-06-02 */#include <sys/ipc.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/shm.h> #include <sys/types.h> #include <unistd.h>// 消息結(jié)構(gòu)體 typedef struct{char content[128]; } msg;main(int argc, char** argv) {int shm_id,i;key_t key;msg *pMsg;if (argc < 2){printf("invalid argument\n");return ;}// key簡單寫死key = 9999;// 創(chuàng)建共享內(nèi)存shm_id=shmget(key,4096,IPC_CREAT);if(shm_id == -1){perror("shmget error");return;}// 映射共享內(nèi)存到進(jìn)程地址空間pMsg=(msg*)shmat(shm_id, NULL, 0);if (pMsg == (void *)-1){perror("shmat error");return ;}// 寫數(shù)據(jù)到共享內(nèi)存memcpy(pMsg->content, argv[1], strlen(argv[1]));// 取消共享內(nèi)存映射,并沒有刪除共享內(nèi)存if(shmdt(pMsg) == -1){perror(" detach error ");}return ; }

    3.2 共享內(nèi)存讀示例

    /* ** Name: shm_read.c ** Desc: 共享內(nèi)存讀端 ** Author: masonf ** Date: 2020-06-02 */#include <sys/ipc.h> #include <stdio.h> #include <sys/shm.h> #include <errno.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> typedef struct{char content[128]; } msg;void main(int argc, char** argv) {int shm_id,i;key_t key;msg *pMsg = NULL;// 使用固定值key = 9999;// 存在則直接返回共享內(nèi)存shm_id = shmget(key, 4096, IPC_CREAT); if(shm_id == -1){perror("shmget error");return;}// 映射共享內(nèi)存到進(jìn)程自身地址空間pMsg = (msg*)shmat(shm_id,NULL,0);if (pMsg == NULL){printf("shmat error, errno:%d", errno);return ;}printf("Get Msg from shm_id:%s\n", pMsg->content);// 取消共享內(nèi)存映射if(shmdt(pMsg) == -1){perror(" detach error ");}return; }

    4. 運行

    5.?注意事項

  • 當(dāng)多個進(jìn)程同時讀寫共享內(nèi)存存在競態(tài)沖突,需要用戶自己做好互斥,可以使用信號量等機(jī)制。
  • 共享內(nèi)存具有內(nèi)核持久性,除非手動調(diào)用shmctl刪除,否則會一直存在,直到系統(tǒng)重啟。
  • fork后執(zhí)行exec,則共享內(nèi)存會自動解除映射,detach
  • 創(chuàng)建共享內(nèi)存有一些限制。
    • shmmax? 單個共享內(nèi)存塊最大字節(jié)數(shù)
    • shmmnb? 共享內(nèi)存空間最小字節(jié)數(shù)
    • shmmni? 系統(tǒng)最多可以創(chuàng)建的共享內(nèi)存數(shù)量
    • shmseg? 單個進(jìn)程最多可以映射的共享內(nèi)存數(shù)量
    • shmall? ?系統(tǒng)可供使用的共享內(nèi)存大小

    6. 參考資料

    1.?https://linux.die.net/man/2/shmctl

    https://linux.die.net/man/2/shmget

    2. 《Linux環(huán)境編程 從應(yīng)用到內(nèi)核》

    3. 《Unix網(wǎng)絡(luò)編程 卷二 進(jìn)程間通信》

    ?

    ================================================================================================

    Linux應(yīng)用程序、內(nèi)核、驅(qū)動、后臺開發(fā)交流討論群(745510310),感興趣的同學(xué)可以加群討論、交流、資料查找等,前進(jìn)的道路上,你不是一個人奧^_^。...
    ?

    ?

    總結(jié)

    以上是生活随笔為你收集整理的Linux进程间通信一 System V 共享内存简介与示例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。