Shared Memory
1. Shared Memory介绍
共享内存是System V版本的最后一个进程间通信方式。共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存, 共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。 进程可以将同一段物理内存连接到他们自己的地址空间中,所有的进程都可以访问共享内存中的地址。 如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程.
特别提醒:共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前, 并无自动机制可以阻止第二个进程开始对它进行读取,所以我们通常需要用其他的机制来同步对共享内存的访问,例如信号量.
2. C语言demo程序
//comm.h
#ifndef _COMM_H__
#define _COMM_H__
#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#define PATHNAME "."
#define PROJ_ID 0x6666
int CreateShm(int size);
int DestroyShm(int shmid);
int GetShm(int size);
#endif
//comm.c
#include"comm.h"
static int CommShm(int size,int flags)
{
key_t key = ftok(PATHNAME,PROJ_ID);
if(key < 0)
{
perror("ftok");
return -1;
}
int shmid = 0;
if((shmid = shmget(key,size,flags)) < 0)
{
perror("shmget");
return -2;
}
return shmid;
}
int DestroyShm(int shmid)
{
if(shmctl(shmid,IPC_RMID,NULL) < 0)
{
perror("shmctl");
return -1;
}
return 0;
}
int CreateShm(int size)
{
return CommShm(size,IPC_CREAT | IPC_EXCL | 0666);
}
int GetShm(int size)
{
return CommShm(size,IPC_CREAT);
}
//client.c
#include"comm.h"
int main()
{
int shmid = GetShm(4096);
sleep(1);
char *addr = shmat(shmid,NULL,0);
sleep(2);
int i = 0;
while(i < 26)
{
addr[i] = 'A' + i;
i++;
addr[i] = 0;
sleep(1);
}
shmdt(addr);
sleep(2);
return 0;
}
//server.c
#include"comm.h"
int main()
{
int shmid = CreateShm(4096);
char *addr = shmat(shmid,NULL,0);
sleep(2);
int i = 0;
while(i++ < 26)
{
printf("client# %s\n",addr);
sleep(1);
}
shmdt(addr);
sleep(2);
DestroyShm(shmid);
return 0;
}
//Makefile
.PHONY:all
all:server client
client:client.c comm.c
gcc -o $@ $^
server:server.c comm.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f client server
#运行结果
[dongfeng@localhost shm]$ ./server
client#
client#
client#
client#
client#
client#
client#
client# A
client# AB
client# ABC
client# ABCD
client# ABCDE
client# ABCDEF
client# ABCDEFG
client# ABCDEFGH
client# ABCDEFGHI
client# ABCDEFGHIJ
client# ABCDEFGHIJK
client# ABCDEFGHIJKL
client# ABCDEFGHIJKLM
client# ABCDEFGHIJKLMN
client# ABCDEFGHIJKLMNO
client# ABCDEFGHIJKLMNOP
client# ABCDEFGHIJKLMNOPQ
client# ABCDEFGHIJKLMNOPQR
client# ABCDEFGHIJKLMNOPQRS