共享內存允許兩個或多個進程共享一個給定的存儲區。因為數據不需要在兩個進程之間進行復制,所以這是一種最快的進程間通信方式。使用共享存儲區的唯一竅門是多個進程之間對一個給定的存儲區的同步訪問。通常信號量被用來實現對共享存儲訪問的同步。
在linux系統中系統共享存儲段的做大字節數為33554432,最小字節數為1;系統中共享存儲段的最大段數4096,每個進程共享存儲段的最大段數為4096.
獲得共享內存標識符:
[cpp]
#include <sys/shm.h>
int shmget(key_t key, size_t size, int flag);
返回值:成功返回共享內存ID,失敗返回-1
#include <sys/shm.h>
int shmget(key_t key, size_t size, int flag);
返回值:成功返回共享內存ID,失敗返回-1 參數size是共享內存的段的大小,如果正在創建一個新段,則必須指定size的大小,如果正在引用一個現存的段,則將size設置為0.
參數flag是表示對該段的操作,創建段的時候該標志應該為IPC_CREAT|0666,IPC_CREAT為創建共享內存,0666為可讀可寫權限。
參數key,鍵。這個概念比較模糊。通過函數ftok函數獲得一個key。
[html]
#include <sys/ipc.h>
key_t ftok(const char *path, int id);
返回值:成功返回鍵值,出錯返回-1
#include <sys/ipc.h>
key_t ftok(const char *path, int id);
返回值:成功返回鍵值,出錯返回-1 path參數必須是一個存在的文件。
共享內存創建完成後,就可以使用shmat函數將其連接到它的地址空間中。
[html]
#include <sys/shm.h>
void *shmat(int shmid, const void *addr, int flag);
返回值:成功返回指向共享內存的指針,出錯返回-1
#include <sys/shm.h>
void *shmat(int shmid, const void *addr, int flag);
返回值:成功返回指向共享內存的指針,出錯返回-1 共享存儲段連接到調用進程的那個地址上與addr參數以及在flag中是否指定SHM_RND位有關。
1、如果addr為0,則此段連接到由內核選擇的第一個可用地址上,這是推薦的使用方式
2、如果addr非0,並且沒有指定SHM_RND,則此段連接到addr所指的地址上。
除非指定在一種硬件上使用運行應用程序,否則是不應該指定共享內存所連接到的地址,所以一般addr指定位0,以便由內核選擇地址。
對共享內存操作結束後,調用函數shmdt脫離該共享內存。注意,這並不是從系統中刪除其標識符以及其數據結構,該標識符依然存在,直到某個進程調用shmctl特地刪除,後面介紹shmctl函數。
[html]
#include <sys.shm.h>
int shmdt(void *addr)
返回值:成功返回0,出錯返回-1.
#include <sys.shm.h>
int shmdt(void *addr)
返回值:成功返回0,出錯返回-1.
shmctl函數對共享內存執行多種操作。
[html] view plaincopyprint?#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds, *buf);
返回值:成功返回0,失敗返回-1.
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds, *buf);
返回值:成功返回0,失敗返回-1. cmd參數指定下列5個命令,使其在shmid指定的共享內存上執行。
1、IPC_STAT 去此段的shmid_ds結構,並將它存放在由buf指向的結構中。
2、IPC_RMID從系統中刪除共享內存段。我們用的最多的。
下面是我寫的一個關於共享內存使用的程序;
[html]
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int sharememorycom;
//調試打印宏定義
#define DBG(level,fmt,para...) \
{ \
if(level) \
printf(fmt "\tFrom FileName:%s Function:%s Line:%d\n" , ##para, __FILE__, __FUNCTION__, __LINE__); \
}
#define DBG_INFOR 0x01 //正常打印信息
#define DBG_WARNING 0x02 //處理警告異常
#define DBG_ERROR 0x04 //處理錯誤
#define SUCCESS 1
#define FAIL -1
typedef struct
{
int lx;
int zt;
} sharem;
key_t shmkey;
int createShm()
{
int shm_id = 0;
static char *shmname = "aaa";
shmkey = ftok(shmname,0);
if(shmkey==FAIL)
{
DBG(DBG_ERROR, "get shm key failure!\n");
return FAIL;
}
shm_id=shmget(shmkey,4096,IPC_CREAT|0666);
if(shm_id==FAIL)
{
DBG(DBG_ERROR, "creat shm is fail\n");
perror("error");
return FAIL;
}
return SUCCESS;
}
int setshareshm(int lx,int zt)
{
int shm_id;
sharem *p_map;
shm_id=shmget(shmkey,4096,0666);
if(shm_id==FAIL)
{
DBG(DBG_ERROR, "creat shm is fail\n");
perror("error");
return FAIL;
}
p_map=(sharem*)shmat(shm_id,NULL,0);
(*p_map).lx=lx;
(*p_map).zt=zt;
if(shmdt(p_map)==FAIL)
return FAIL;
return 0x00;
}
int getshareshm()
{
int shm_id;
int lx = 0;
int zt = 0;
sharem *p_map;
shm_id=shmget(shmkey,4096,0666);
if(shm_id==FAIL)
{
DBG(DBG_ERROR, "creat shm is fail\n");
perror("error");
return FAIL;
}
p_map = (sharem*)shmat(shm_id,NULL,0);
lx = (*p_map).lx;
zt = (*p_map).zt;
printf("lx = %d, zt = %d\n", lx, zt);
if(shmdt(p_map)==FAIL)
return FAIL;
return zt;
}
void sharememory()
{
static int count = 0;
setshareshm(count, 0);
count++;
getshareshm();
}
int main(void)
{
createShm();
while (1)
{
sharememory();
usleep(10*1000);
}
return 0;
}
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int sharememorycom;
//調試打印宏定義
#define DBG(level,fmt,para...) \
{ \
if(level) \
printf(fmt "\tFrom FileName:%s Function:%s Line:%d\n" , ##para, __FILE__, __FUNCTION__, __LINE__); \
}
#define DBG_INFOR 0x01 //正常打印信息
#define DBG_WARNING 0x02 //處理警告異常
#define DBG_ERROR 0x04 //處理錯誤
#define SUCCESS 1
#define FAIL -1
typedef struct
{
int lx;
int zt;
} sharem;
key_t shmkey;
int createShm()
{
int shm_id = 0;
static char *shmname = "aaa";
shmkey = ftok(shmname,0);
if(shmkey==FAIL)
{
DBG(DBG_ERROR, "get shm key failure!\n");
return FAIL;
}
shm_id=shmget(shmkey,4096,IPC_CREAT|0666);
if(shm_id==FAIL)
{
DBG(DBG_ERROR, "creat shm is fail\n");
perror("error");
return FAIL;
}
return SUCCESS;
}
int setshareshm(int lx,int zt)
{
int shm_id;
sharem *p_map;
shm_id=shmget(shmkey,4096,0666);
if(shm_id==FAIL)
{
DBG(DBG_ERROR, "creat shm is fail\n");
perror("error");
return FAIL;
}
p_map=(sharem*)shmat(shm_id,NULL,0);
(*p_map).lx=lx;
(*p_map).zt=zt;
if(shmdt(p_map)==FAIL)
return FAIL;
return 0x00;
}
int getshareshm()
{
int shm_id;
int lx = 0;
int zt = 0;
sharem *p_map;
shm_id=shmget(shmkey,4096,0666);
if(shm_id==FAIL)
{
DBG(DBG_ERROR, "creat shm is fail\n");
perror("error");
return FAIL;
}
p_map = (sharem*)shmat(shm_id,NULL,0);
lx = (*p_map).lx;
zt = (*p_map).zt;
printf("lx = %d, zt = %d\n", lx, zt);
if(shmdt(p_map)==FAIL)
return FAIL;
return zt;
}
void sharememory()
{
static int count = 0;
setshareshm(count, 0);
count++;
getshareshm();
}
int main(void)
{
createShm();
while (1)
{
sharememory();
usleep(10*1000);
}
return 0;
}