固然只有mmap是能夠的,不過因爲各類不一樣的系統的架構不同,後來又通過整合,因此咱們如今的linux有多種內存共享方案,下面在介紹一種很是經常使用的系統V內存方案。
本人在本身理解的基礎上一步一步去深刻
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int shmid;
char *shmadd;
struct shmid_ds shmbuf;
if((shmid=shmget(IPC_PRIVATE,1000,0666))<0)
{perror(
"shmget");
exit(1);}
else printf(
"created shared-memory: %d\n",shmid);
system(
"ipcs -m");
if((shmadd=shmat(shmid,0,0))<(char *)0)
{ perror(
"shmat");
exit(1); }
else printf(
"attached shared-memory\n");
system(
"ipcs -m");
if((shmdt(shmadd))<0) //禁止本進程再使用該共享內存區
{perror(
"shmdt");
exit(1);}
else printf(
"deleted shared-memory\n");
system(
"ipcs -m");
if(shmctl(shmid,IPC_RMID,&shmbuf)<0)
{perror(
"shmctl");
exit(1);}
system(
"ipcs -m");
return 0;
}
shmget
int shmget(key_t
key, size_t
size, int
flag);
key: 標識符的規則
size:共享存儲段的字節數
flag:讀寫的權限
返回值:成功返回共享存儲的id,失敗返回-1
shmat
void *shmat(int
shmid, const void *
addr, int
flag);
shmid:共享存儲的id
addr:通常爲0,表示鏈接到由內核選擇的第一個可用地址上,不然,若是flag沒有指定SHM_RND,則鏈接到addr所指定的地址上,若是flag爲SHM_RND,則地址取整
flag:如前所述,通常爲0
返回值:若是成功,返回共享存儲段地址,出錯返回-1
shmdt
int shmdt(void *addr);
addr:共享存儲段的地址,之前調用shmat時的返回值
shmdt將使相關shmid_ds結構中的shm_nattch計數器值減1
shmctl
int shmctl(int shmid,int cmd,struct shmid_ds *buf)
shmid:共享存儲段的id
cmd:一些命令,有:IPC_STAT,IPC_RMID,SHM_LOCK,SHM_UNLOCK
程序說明:
結合我一些函數的說明,這個程序應該就很容易懂了,另外須要補充的是,查看共享內存段的命令式:ipcs -m,刪除共享內存段的命令是:ipcrm -m shmid,請注意,共享內存不會隨着程序結束而自動消除,要麼調用shmctl刪除,要麼本身用手敲命令去刪除,不然永遠留在系統中
另看
ipc_write.c
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct
{
char name;
int age;
}people;
int main(int argc,char **argv)
{
int shm_id,i;
key_t key;
char temp_char;
people *p_map;
shm_id=shmget(IPC_PRIVATE,4096,IPC_CREAT);
if(shm_id<0)
{perror(
"shmget error");return;}
p_map=(people*)shmat(shm_id,
NULL,0);
temp_char=
'a';
for(i=0;i<10;i++)
{
(*(p_map+i)).name=temp_char;
(*(p_map+i)).age=20+i;
temp_char+=1;
}
if(shmdt(p_map)<0)
perror(
"detach error");
return 0;
}
ipc_read.c
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct
{
char name;
int age;
}people;
int main(int argc,char **argv)
{
int shm_id,i;
key_t key;
people *p_map;
struct shmid_ds shmbuf;
shm_id=393216;//393216是ipcs -m查看到的shmid
p_map=(people*)shmat(shm_id,
NULL,0);
for(i=0;i<10;i++)
{
printf(
"name----------%c\n",(*(p_map+i)).name);
printf(
"age------------%d\n",(*(p_map+i)).age);
}
if(shmdt(p_map)<0)
perror(
"shmdt error");
if(shmctl(shm_id,IPC_RMID,&shmbuf)<0)
perror(
"shmctl error");
return 0;
}
ipc_write.c實現向共享內存裏面寫,ipc_read.c實現從共享內存裏面讀
不過在ipc_write.c的shmget的第一個參數是IPC_PRIVATE,因此分配的key的值是
由系統產生的,而且沒有任何標誌獨特性的key_t的值。那麼ipc_read.c是如何知道shm_id的呢?我這個是本身手工查ipcs -m得來的,那麼編程中如何實現呢?
1.創建具備很是鮮明特徵,獨特的key值
2.經過信號量,消息隊列或者管道(FIFO)傳輸這個shm_id
shm_id也有人用,不過稍微麻煩一點,下面介紹用第一種方法
shm_ftok_write.c
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct
{
char name;
int age;
}people;
int main(int argc,char **argv)
{
int shm_id,i;
key_t key;
char temp_char;
people *p_map;
char *name=
"/dev/shm/myshm1";
key = ftok(name,0);
printf(
"key=%d\n",key);
if(key==-1)
perror(
"ftok error");
shm_id=shmget(IPC_PRIVATE,4096,IPC_CREAT);
printf(
"shm_id=%d\n",shm_id);
if(shm_id==-1)
{perror(
"shmget error");return;}
p_map=(people*)shmat(shm_id,
NULL,0);
temp_char=
'a';
for(i=0;i<10;i++)
{
(*(p_map+i)).name=temp_char;
temp_char+=1;
(*(p_map+i)).age=20+i;
}
if(shmdt(p_map)==-1)
perror(
"detach error");
return 0;
}
ipc_ftok_read.c
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct
{
char name;
int age;
}people;
int main(int argc,char **argv)
{
int shm_id,i;
key_t key;
people *p_map;
char *name=
"/dev/shm/myshm1";
key = ftok(name,0);
if(key==-1)
perror(
"ftok error");
shm_id=shmget(key,4096,IPC_CREAT);
printf(
"shm_id=%d\n",shm_id);
if(shm_id==-1)
{perror(
"shmget error");return;}
p_map=(people*)shmat(shm_id,
NULL,0);
p_map=(people*)shmat(393216,
NULL,0);
for(i=0;i<10;i++)
{
printf(
"name----------%c\n",(*(p_map+i)).name);
printf(
"age-----------%d\n",(*(p_map+i)).age);
}
if(shmdt(p_map)==-1)
perror(
"detach error");
return 0;
}
這裏用的是獨特鮮明的key值
執行程序以前,先建立
"/dev/shm/myshm1"文件
最好是寫成本身的執行文件的目錄,如"/home/nsl/myprogram/ipc_ftok_write"這樣就不會存在文件不存在的狀況了
ftok
key_t ftok( char * fname, int id )
frame:文件的全路徑,要求文件存在且進程可訪問
id:第幾個共享內存
返回值:返回key值
註明:系統V共享內存與mmap相比,就是系統V共享內存歷來不把數據真正寫到磁盤文件中去,而mmap機制在munmap的時候將數據寫到磁盤文件
發現原來系統V共享內存也須要文件的支撐
固然,共享內存沒有這麼容易,還有大量的同步要作
再補充點共享內存的派系知識:
UNIX進程間通訊方式包括:管道、FIFO、信號。
System V進程間通訊方式包括:System V消息隊列、
System V信號燈、System V共享內存。
POSIX進程間通訊包括:posix消息隊列、posix信號
燈、posix共享內存。
我的以爲,mmap是posix共享內存
shmget是System V共享內存