进程间通信-共享内存

共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC通信形式。是针对其他通信机制运行效率较低而设计的,往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。

机制如下:


特点:

1.内存共享是进程间通信速度最快的:

由上图可知,内存共享是进程1从其地址空间直接写到物理内存中,进程2则直接通过地址空间虚拟地址从内存中取,不需要通过进入内核来传递消息,而消息队列,信号量则都要在内核开辟一块空间,进程通信传递需从用户区拷贝到内核区,再从内核区拷贝到用户区,所以其不涉及内核的拷贝,所以其效率较高。

2.共享内存不带任何同步、互斥机制,所以其一般都与信号量匹配使用;

3.共享内存开辟在物理内存上,所以其生命周期为随内核。


Linux下共享内存的两条命令:

ipcs   -m  ;           //查看共享内存
ipcrm -m  <shmid>;    //删除共享内存


共享内存函数:

1.创建共享内存:

函数:

int shmget(key_t key,size_t size,int shmflag);
参数:

key:共享内存唯一的键值,用ftok()函数获取;

size:申请的内存大小,一般为页的整数倍,因为系统分配的大小始终为页的整数倍,1页=4k;

shmflag:IPC_CREAT(单独使用没有创建共享内存,创建新的共享内存,若有,则返回存在的共享内存),IPC_EXCL(与IPC_CREAT合用,不存在,创建新的,存在返回错误码);

返回值:

成功返回共享内存id,失败返回错误码。


2.删除共享内存:

函数:

int shmctl(int shmid,int cmd,struct shmid_ds* buf);
参数:

shmid:共享内存id;

cmd:删除时设为IPC_IMID;

buf:对共享内存的修改或对其查看,若cmd设为IPC_IMID,则设为NULL;


3.共享内存的挂接:

函数:(此函数用法与malloc()相同)

void* shmat(int shmid,const void* shmaddr,int shmflg);
参数:

shmid:共享内存id;

shmaddr:共享内存与指定虚拟地址建立映射关系,一般设为NULL,即由操作系统安排;

shmflg:一般设为缺省0;

返回值:

建立映射关系后返回的虚拟地址。

4.与共享内存断开联系:

函数:

int shmdt(const void* shmaddr);
参数:

shmaddr:shmat()函数的返回值虚拟地址;

代码实现:

comm.h

#ifndef _COMM_H__
#define _COMM_H__

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>

#define PATH "."
#define PROJ_ID 0x6666

int creatShm(int size);    //创建 
int getShm(int size);     //获取 
int destroyShm(int shmid);  //删除 

#endif   //_COMM_H__


server.c(读打印)

#include "comm.h"

int main()
{
	int shmid=creatShm(4096);   //创建共享内存 
    //printf("create success!!!  shmid:%d\n",shmid); 
	
	sleep(3);
	char* addr=shmat(shmid,NULL,0);  //使当前进程与共享内存挂接 ,此函数返回进程虚拟地址 
	int i=0;                         //第二个参数为指定的虚拟地址,一般由操作系统指定,所以设为null 
	while(i<26)
	{
		printf("%s\n",addr);      //打印地址(读共享内存处内容)处内容    
		sleep(1);		
		++i;
	}
	
	shmdt(addr);    //使当前进程与共享内存断开关联 

	int ret=destroyShm(shmid);
	//printf("destroy success. ret:%d\n",ret);

	return 0;
}

client.c(写)

#include "comm.h"

int main()
{
	int shmid=getShm(4096);   //获取已创建好的共享内存 
	printf("getShm success!!  shmid:%d\n",shmid);
	
	char* addr=shmat(shmid,NULL,0);    //使当前进程与共享内存挂接 ,此函数返回进程虚拟地址 
	int i=0;
	while(i<26)
	{
		addr[i]='A'+i;   //向共性内存处写内容 
		sleep(1);
		++i;
		addr[i]=0;
	}

	shmdt(addr);    //使当前进程与共享内存断开关联
	return 0;
}
comm.c

#include "comm.h"

static int commShm(int size,int flags)   
{
	key_t _key=ftok(PATH,PROJ_ID);
	if(_key<0)
	{
		perror("ftok");
		return -1;
	}
	int shmid=shmget(_key,size,flags);  //创建或获取共享内存 参数size为页的整数倍(会自动调整)  1页=4k
	if(shmid<0)
	{
		perror("shmget");
		return -2;
	}
	return shmid;
}


int creatShm(int size)
{
	return commShm(size,IPC_CREAT|IPC_EXCL|0666);
}

int getShm(int size)
{
	return commShm(size,IPC_CREAT);
}

int destroyShm(int shmid)
{
	if(shmctl(shmid,IPC_RMID,NULL)<0)  //立即删除shmid标识的共享内存 
	{
		perror("destroy:shmctl");
		return -1;
	}
	return 0;
}


效果如下:








发布了85 篇原创文章 · 获赞 56 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章