特点
共享内存是linux进程进行通信的一种高效的传递方式,linux内核在内存中留下一块存储区,进程通过将共享内存的地址映射到进程空间,就可以实现直接对数据进行操作,但是共享内存自身没有同步机制,因此需要适用其他的方式实现对共享内存空间的读写进行同步。通信结构简图如图1所示。
图1 多进程共享内存通信原理示意图
实现过程与操作函数
共享内存的操作分为以下几个步骤:
- 创建共享内存
- 映射共享内存
- 删除共享内存
- 释放共享内存
/************************************
int shmget(key_t key, size_t size, int shmflg);
//创建共享内存
//size 共享内存的大小,
shmflag类似于前面的消息队列和信号量的创建,
采用一般采用0666|IPC_CREAT,实现不存在内存空间的时候实现创建,存
在的时候实现获取共享内存,返回创建的内存的标志符
----------
void *shmat(int shmid, const void *shmaddr, int shmflg);
//映射共享内存
shmid为创建时的标志符;
shmaddr:将共享内存映射到指定位置(若为 0 则表示把该段共享内存
映射到调用进程的地址空间)
shmflg:
SHM_RDONLY:共享内存只读
默认 0:共享内存可读写
----------
int shmdt(const void *shmaddr);
//释放共享内存Shmaddr:被映射的共享内存段地址,
----------
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
// 删除共享内存
shmid
共享内存标识符
cmd
IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的
uid、gid、mode复制到共享内存的shmid_ds结构内
IPC_RMID:删除这片共享内存
buf
共享内存管理结构体。
/*************************************************/
应用实例
实现两个进程通过共享内存交换数据,发送端接收终端数据,发送至共享内存,读取端从共享内存读取数据,实现数据的交换。由于共享内存自身无法实现进程同步,因此定义了write_flag标志位,作为读写的标志实现
读取端例程
#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include "shmheader.h"
#include <string.h>`
int main()
{
int shm_id;
int run_flag=1;
void *shm_mem=NULL;
struct shared_mem *shared;//用来存放地址
shm_id=shmget((key_t)1234,sizeof(struct shared_mem),0666|IPC_CREAT);// 创建共享内存
if(shm_id==-1)
{
printf("Creat shared_mem failed\n");
exit(EXIT_FAILURE);
}
// 将共享内存链接到当前进程
shm_mem=shmat(shm_id,(void *)0,0);
if(shm_mem==(void *)-1)
{
printf("connect memeory failed\n");
exit(EXIT_FAILURE);
}
//打印地址
shared=(struct shared_mem *)shm_mem;
shared->write_flag=0;
while(run_flag)
{
if(shared->write_flag==1)// 等待写结束
{
printf("You Write is:%s",shared->text);
sleep(1);
shared->write_flag=0;
if(strncmp(shared->text,"end",3)==0)
{
run_flag=0;
}
}
}
if(shmdt(shm_mem)==-1)
{
printf("disconnect memeory failed!\n");
exit(EXIT_FAILURE);
}
//读取结束要删除共享内存
if(shmctl(shm_id,IPC_RMID,0)==-1)
{
printf("delete memeory failed!\n");
exit(EXIT_FAILURE);
}
sleep(2);
return 0;
}`
发送端例程
#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include "shmheader.h"
#define BUF_SIZE 512
int main()
{
int shm_id;
int run_flag=1;
void *shm_mem=NULL;
struct shared_mem *shared;//用来存放地址
char buffer[BUF_SIZE+1];
shm_id=shmget((key_t)1234,sizeof(struct shared_mem),0666|IPC_CREAT);// 创建共享内存
if(shm_id==-1)
{
printf("Creat shared_mem failed\n");
exit(EXIT_FAILURE);
}
// 将共享内存链接到当前进程
shm_mem=shmat(shm_id,(void *)0,0);
if(shm_mem==(void *)-1)
{
printf("connect memeory failed\n");
exit(EXIT_FAILURE);
}
//打印地址
// printf("share mameory adress is %X\n",(int)shm_mem);
shared=(struct shared_mem*)shm_mem;
//shared.write_flag=1; //关闭写
while(run_flag)
{
//一直检测写
while(shared->write_flag) //如果 一直不可写再次等待
{
sleep(1);
printf("please waiting ....\n");
}
printf("please write :");
fgets(buffer,BUF_SIZE,stdin);
strncpy(shared->text,buffer,BUF_SIZE);
shared->write_flag=1;
if(strncmp(buffer,"end",3)==0)
{
run_flag=0;
}
}
if(shmdt(shm_mem)==-1)
{
printf("disconnect memeory failed!\n");
exit(EXIT_FAILURE);
}
sleep(2);
return 0;
}
头文件
#ifndef _SHMHEADER_H
#define _SHMHEADER_H
#define TEXT_SIZE 2048
struct shared_mem
{
int write_flag;//定义的读写标志位
char text[TEXT_SIZE];
};
#endif
总结
使用共享内存实现进程通信,接口简单、通信方便、效率高;但是缺乏同步机制,需要借用其他的方法实现同步。