Linux进程间通信一 System V 共享内存简介与示例
目錄
1. System V共享內存簡介
2. API介紹
2.0 key_t和標識符
2.1? 創建system v共享內存
2.2 映射共享內存并使用
2.3?取消共享內存映射
2.4?控制共享內存
3. 實例
3.1 共享內存寫示例
3.2 共享內存讀示例
4. 運行
5.?注意事項
6. 參考資料
1. System V共享內存簡介
System V IPC通常指的是以下三種:
System V IPC最早是在上世紀70年代末由貝爾實驗室開發出來,三種IPC在實現架構、使用方式上有很多相同之處,比如內核實現里共用了ipc_perm權限管理結構體,使用方式上都包括基本的xxxget,xxxctl等等。今天主要介紹下System V 共享內存的使用方式。共享內存作為IPC通信中最快的一種,之所以快是因為一旦創建成功,后續操作無需內核拷貝數據以及系統調用,通信雙方可以直接操作共享內存來通信。因為開發出來比較早,所以存在一些缺陷,所以就有了Posix IPC的產生,不過這是后話,在此不提。首先看下共享內存的接口。
2. API介紹
2.0 key_t和標識符
System V IPC對象通過標識符來區分,該標志符具有系統唯一性,是操作系統內的全局變量。生成SystemV IPC對象的Get函數需要一個key_t參數,這是一個整型變量,用于對應一個標識符。該標識符通常有三種方法生成:
?
2.1? 創建system v共享內存
可以使用ipcs | ipcrm | ipcmk 查看、刪除和創建共享內存
#include <sys/ipc.h> #include <sys/shm.h>/** * @brief 創建共享內存ID * * @params key 與shm_id關聯的key,三種生成方式,包括IPC_PRIVATE,注意key和shm_id不是綁定關系,相同的key產生的標識符不一定相同。 * @params size 共享內存的大小,必須是正整數。 * @params shmflg 標志位和權限控制標志位,可以多個用or運算。IPC_CREAT、 IPC_EXCL * * @returns 成功返回shmid,失敗返回-1 */int shmget(key_t key, size_t size, int shmflg);根據標志位的不同,有如下幾種情況:
| oflag參數 | key不存在 | key已經存在 |
| 無特殊標志位 | 返回-1 | 返回標識符 |
| IPC_CREAT | 返回新建標識符 | 返回已有標識符 |
| IPC_CREAT|IPC_EXCL | 返回新建標識符 | 返回-1 |
?
2.2 映射共享內存并使用
使用共享內存前需要將其映射到經常自身地址空間,之后就可以像malloc分配的內存一樣使用了
#include <sys/types.h> #include <sys/shm.h>/** * @brief 映射共享內存到進程指定地址 * * @params shmid 共享內存標識符 * @params shmaddr 映射的地址,為NULL則內核自動選擇合適的地址,非空并且設置SHM_RND標志位,則自動對齊,如果沒有此標志位并且不對齊,報錯。 * @params shmflg 可以設置SHM_RND、SHM_REMAP,SHM_RDONLY * 如果映射的地址已經有了映射,可以設置SHM_REMAP標志位重新映射,否則報錯。 * 如果地址不對齊,可以設置SHM_RND標志位,此時內核自動找到符合符合要求的地址,否則報錯。 * * @returns 成功返回映射地址,可以像malloc返回的地址那樣操作,失敗返回 (void *) -1 */void *shmat(int shmid, const void *shmaddr,int shmflg);2.3?取消共享內存映射
#include <sys/types.h> #include <sys/shm.h>/** * @brief 取消共享內存映射 * * @params shmaddr shmat返回的共享內存地址 * * 只是減少共享內存的引用計數并未實際刪除共享內存 * * @returns 成功返回0,失敗返回 -1 */int shmdt(const void *shmaddr);2.4?控制共享內存
#include <sys/ipc.h> #include <sys/shm.h>struct shmid_ds {struct ipc_perm shm_perm; /* 所有權及權限 */size_t shm_segsz; /* 共享內存大小 (bytes) */time_t shm_atime; /* 上次shmat時間 */time_t shm_dtime; /* 上次shmdt時間 */time_t shm_ctime; /* 上次修改時間 */pid_t shm_cpid; /* 創建進程皮帶 */pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */shmatt_t shm_nattch; /* 當前shmat進程數量 */... };/** * @brief 取消共享內存映射 * * @params shmid 共享內存標識符 * @params cmd 控制命令,IPC_STAT, IPC_SET, IPC_RMID, SHM_LOCK, SHM_UNLOCK * @params buf 緩存 * IPC_STAT 獲取對應共享內存信息,存到buf緩存里。 * IPC_SET 只能修改shm_perm里面的uid,gid及mode * IPC_RMID 刪除共享內存,只有引用計數為0才真正刪除 * SHM_LOCK 阻止共享內存被替換出去 * SHM_UNLOCK 和SHM_LOCK相反 * * @returns 成功返回0,失敗返回 -1 */int shmctl(int shmid, int cmd, struct shmid_ds *buf);3. 實例
3.1 共享內存寫示例
/* ** Name: shm_write.c ** Desc: 共享內存寫端 ** 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>// 消息結構體 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;// 創建共享內存shm_id=shmget(key,4096,IPC_CREAT);if(shm_id == -1){perror("shmget error");return;}// 映射共享內存到進程地址空間pMsg=(msg*)shmat(shm_id, NULL, 0);if (pMsg == (void *)-1){perror("shmat error");return ;}// 寫數據到共享內存memcpy(pMsg->content, argv[1], strlen(argv[1]));// 取消共享內存映射,并沒有刪除共享內存if(shmdt(pMsg) == -1){perror(" detach error ");}return ; }3.2 共享內存讀示例
/* ** Name: shm_read.c ** Desc: 共享內存讀端 ** 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;// 存在則直接返回共享內存shm_id = shmget(key, 4096, IPC_CREAT); if(shm_id == -1){perror("shmget error");return;}// 映射共享內存到進程自身地址空間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);// 取消共享內存映射if(shmdt(pMsg) == -1){perror(" detach error ");}return; }4. 運行
5.?注意事項
- shmmax? 單個共享內存塊最大字節數
- shmmnb? 共享內存空間最小字節數
- shmmni? 系統最多可以創建的共享內存數量
- shmseg? 單個進程最多可以映射的共享內存數量
- shmall? ?系統可供使用的共享內存大小
6. 參考資料
1.?https://linux.die.net/man/2/shmctl
https://linux.die.net/man/2/shmget
2. 《Linux環境編程 從應用到內核》
3. 《Unix網絡編程 卷二 進程間通信》
?
================================================================================================
Linux應用程序、內核、驅動、后臺開發交流討論群(745510310),感興趣的同學可以加群討論、交流、資料查找等,前進的道路上,你不是一個人奧^_^。...
?
?
總結
以上是生活随笔為你收集整理的Linux进程间通信一 System V 共享内存简介与示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: w7系统不能显示u盘启动不了怎么办 解决
- 下一篇: Linux进程间通信二 System V