共享內(nèi)存指 (shared memory)在多處理器的計(jì)算機(jī)系統(tǒng)中,可以被不同中央處理器(CPU)訪問的大容量?jī)?nèi)存。--百度百科
上述已經(jīng)將共享內(nèi)存的概念說的很清晰了,簡(jiǎn)單理解就是多個(gè)進(jìn)程可共用一片存儲(chǔ)內(nèi)存。
Linux已經(jīng)提供了共享內(nèi)存的接口,本文主要簡(jiǎn)單介紹此接口使用方法及使用實(shí)例。
接口說明設(shè)置共享存儲(chǔ)標(biāo)識(shí)符:
設(shè)定共享內(nèi)存的標(biāo)識(shí)符,用于讀寫時(shí)唯一許可。
/**
* @brief: returns the identifier of the System V shared memory
* segment associated with the value of the argument key.
*
* @param - key: identification of the IPC
* @param - size: the size of shared memory usage
* @param - shmflg: If shmflg specifies both IPC_CREAT and IPC_EXCL
* and a shared memory segment already exists for key, then shmget()
* fails with errno set to EEXIST.
*
* @return On success, a valid shared memory identifier is returned.
* On error, -1 is returned, and errno is set to indicate the error.
*/int shmat(key_t key, size_t size, int shmflg)
將共享字段鏈接到地址空間
設(shè)定共享內(nèi)存字段在系統(tǒng)的存儲(chǔ)地址。
/**
* @brief: shmat() attaches the System V shared memory segment
* identified by shmid to the address space of the calling process.
*
* @param - shmid:
* @param - shmaddr: the addr of the System V shared memory
* @param - shmflg:
*
* @return On success, shmat() returns the address of the attached
* shared memory segment;
* on error, (void *) -1 is returned, and errno is set to indicate
* the cause of the error.
*/void *shmat(int shmid, const void *shmaddr, int shmflg)
取消共享地址映射
當(dāng)共享內(nèi)存使用完畢后,調(diào)此接口會(huì)結(jié)束共享內(nèi)存與指定的系統(tǒng)地址的映射關(guān)系。這里并未從系統(tǒng)中刪除標(biāo)識(shí)符,該標(biāo)識(shí)符一直存在直至某個(gè)進(jìn)程帶IPC_RMID命令調(diào)用shmctl特地刪除它為止。
/**
* @brief: detaches the shared memory segment located at the
* address specified by shmaddr from the address space of the calling
* process.
*
* @param - shmaddr: the addr of the System V shared memory
*
* @return On success, shmdt() returns 0;
* on error -1 is returned, and errno is set to indicate the cause of
* the error.
*/int shmdt(const void *shmaddr);
共享內(nèi)存多種操作
類似于驅(qū)動(dòng)ctrl函數(shù),即傳入不同的命令可執(zhí)行不同的操作。cmd可選擇IPC_STAT/IPC_SET/IPC_RMID/SHM_LOCK/SHM_UNLOCK。
IPC_STAT 將與shmid關(guān)聯(lián)的內(nèi)核數(shù)據(jù)結(jié)構(gòu)中的信息復(fù)制到buf所指向的shmid_ds結(jié)構(gòu)中。
IPC_SET 將buf指向的shmid_ds結(jié)構(gòu)的一些成員的值寫入與這個(gè)共享內(nèi)存段相關(guān)聯(lián)的內(nèi)核數(shù)據(jù)結(jié)構(gòu),同時(shí)更新它的shm_ctime成員。
IPC_RMID 標(biāo)記要銷毀的共享內(nèi)存。只有在最后一個(gè)進(jìn)程將它分離之后,共享內(nèi)存才會(huì)被銷毀。
SHM_LOCK 防止讀取共享內(nèi)存。
SHM_UNLOCK 解鎖共享內(nèi)存,允許它被讀取出來。
/**
* @brief: performs the control operation specified by cmd on the
* System V shared memory segment whose identifier is given in shmid.
*
* @param - shmid:
* @param - cmd:
* @param - buf:
*
* @return A successful IPC_INFO or SHM_INFO operation returns the
* index of the highest used entry in the kernel's internal array recording
* information about all shared memory segments. (This information
* can be used with repeated SHM_STAT or SHM_STAT_ANY operations
* to obtain information about all shared memory segments on the system.)
* A successful SHM_STAT operation returns the identifier of the shared
* memory segment whose index was given in shmid. Other operations
* return 0 on success.
* On error, -1 is returned, and errno is set appropriately.
*/int shmctl(int shmid, int cmd, struct shmid_ds *buf)
功能: 使用共享內(nèi)存設(shè)計(jì)兩個(gè)讀寫進(jìn)程,實(shí)現(xiàn)跨進(jìn)程通信。演示:
總結(jié)本文主要接收共享內(nèi)存接口的簡(jiǎn)單使用實(shí)例,其可通過shmctl傳輸不同的指令實(shí)現(xiàn)比較高級(jí)的用法,例如權(quán)限限制。其中共享內(nèi)存也可以配合其他機(jī)制實(shí)現(xiàn)一套比較好用的通信策略,后續(xù)可以玩一玩。
代碼
read.cpp
#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/shm.h>#include "common.h"
int main(int argc, char *argv[]){ int shmid, running = 1; void *shm = NULL; struct ShmData *pShareData = NULL;
shmid = shmget((key_t)SHM_NAME, sizeof(struct ShmData), 0666|IPC_CREAT); if (shmid == -1) { printf("shmget failed! "); exit(0); }
shm = shmat(shmid, 0, 0); if (shm == (void*)-1) { printf("shmat failed! "); exit(0); } printf("Memory attached at %p ", shm);
pShareData = (struct ShmData *)shm; pShareData->flag = 0;
while (running) { if (pShareData->flag) { printf("The memery data: %s", pShareData->data); sleep(rand() % 3); pShareData->flag = 0;
if (!strncmp(pShareData->data, "end", 3)) { running = 0; }
} else { sleep(1); } }
printf("Over! "); if (shmdt(shm) == -1) { printf("shmdt failed! "); exit(0); }
if (shmctl(shmid, IPC_RMID, 0) == -1) { printf("shmctl failed! "); exit(0); }
return 0;}
write.cpp
#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/shm.h>#include "common.h"
int main(int argc, char *argv[]){ int shmid, running = 1; char buffer[DATA_SIZE+1] = {0}; void *shm = NULL; struct ShmData *pShareData = NULL;
shmid = shmget((key_t)SHM_NAME, sizeof(struct ShmData), IPC_EXCL); if (shmid == -1) { printf("shmget failed! "); exit(0); }
shm = shmat(shmid, (void*)0, 0); if (shm == (void*)-1) { printf("shmat failed! "); exit(0); } printf("Memory attached at %p ", shm);
pShareData = (struct ShmData *)shm; //pShareData->flag = 0;
while (running) { while (pShareData->flag == 1) { sleep(1); printf("Waiting... "); }
printf("Input data: "); fgets(buffer, DATA_SIZE, stdin); strncpy(pShareData->data, buffer, DATA_SIZE); pShareData->flag = 1;
if (strncmp(buffer, "end", 3) == 0) { running = 0; } }
if (shmdt(shm) == -1) { printf("shmdt failed! "); exit(0); } sleep(2);
return 0;}
最后
用心感悟,認(rèn)真記錄,寫好每一篇文章,分享每一框干貨。愿每一篇文章不負(fù)自己,不負(fù)看客!
更多文章內(nèi)容包括但不限于C/C++、Linux、開發(fā)常用神器等,可進(jìn)入開源519公眾號(hào)聊天界面回復(fù)“文章目錄” 或者 菜單欄選擇“文章目錄”查看。
本文摘自 :https://blog.51cto.com/u