进程间通信—— 共享内存

进程间通信——共享内存
 进程间通信的方式有信号量,消息队列,管道,今天我们学习进程间通信的另外一种通信方式:共享内存
 共享内存有一个最大的特点就是:以传送数据为目的,在所有进程间通信方式中速度最快的。
原因就是管道消息队列等通信方式,都是在临界资源写好数据之后,读方不读的时候,是不知道写方写入了哪些数据的,
所以就需要拷贝两份数据,但是共享内存是将数据写到物理内存的时候,读方就立刻看到写入的数据。
共享内存原理图:进程间通信—— 共享内存_第1张图片
关于共享内存,系统对于共享内存和消息队列和信号量一样也有一个对应的结构体,如下:
进程间通信—— 共享内存_第2张图片
共享内存的原理就是,让两个进程关联到同一块物理内存,这样读方和写方都可以直接操作,就减少进行数据的拷贝
关于共享内存的创建,需要知道以下几个函数:
①shmget函数:功能:用来创建共享内存
 原型: int shmget(key_t key,size_t size,int shmflg)
  参数:key: 共享内存的名字  size:共享内存的大小  shmflg:由九个标志位组成,和创建文件的mode用法一样
 返回值:成功返回共享内存的标志码,失败返回-1
②shmat函数:功能:把共享内存段连接到进程的地址空间,
原型:void* shmat(int shmid,const void*shmaddr,int shmflg)
参数:shmid:共享内存段的标识符 shmaddr:指定连接的地址 shmflg:SHM_RND和SHM_RDONLY
返回值:成功返回一个指向共享内存第一个字节的指针,失败返回-1
说明:shmaddr为NULL,则让系统自主选择一段空间
③shmdt函数:功能:将共享内存段脱离当前进程
原型:int shmdt(void* shmaddr)
参数:shmaddr:之前shmat返回的参数
返回值:成功返回0,失败返回-1
说明:将共享内存段脱离,不等于将共享内存段删除
④shmctl函数:功能:用于控制共享内存
原型:int shmctl(int shmid,int cmd,struct shmid_ds* buf)
参数:shmid:共享内存标识符  cmd:对应的操作,有三个可取值 buf:指向一个保存着共享内存相关信息的结构
返回值:成功返回0,失败返回-1
说明:cmd对应的取值:
 IPC_STAT:把shmid_ds中的数据设置成共享内存的当前关联值
IPC_SET:在拥有足够权限的情况下,把共享内存当前关联值设置成shmid_ds结构体中给出的值
IPC_RMID:删除共享内存段

      要使用函数已经学习完了,现在我们用代码实现一下共享内存,我们将接口放在我们的myshm.h的头文件里面,创建两个文件,使得两个文件连接一段共享内存:server.c  和 client.c ,在server.c中一直读取共享内存中的内容,我们在client.c中循环写入26个英文字母,这样当运行server.c的时候,就会在屏幕上显示英文字母,一次比上一次多显示一个。

myshm.h文件:

#ifndef _MYSHM_H_
#define _MYSHM_H
#include 
#include 
#include 
#include 

#define PATHNAME "."
#define PROJ_ID 0x6666

static int commShm(int size,int flag)
{
	key_t _key = ftok(PATHNAME,PROJ_ID);
	if(_key<0){
		perror("look ftok");
		return -1;
	}
	int shmid ;
	if((shmid = shmget(_key,size,flag))<0){
		perror("look shmget");
		return -2;
	}
	return shmid;
}
int createShm(int size)
{
	return commShm(size,IPC_CREAT|IPC_EXCL|0666);
}
int getShm(int size)
{
	return commShm(size,IPC_CREAT);
}
int destoryShm(int shmid)
{
	if(shmctl(shmid,IPC_RMID,NULL)<0)
	{
		perror("look shmctl");
		return -1;
	}
}

#endif

server.c文件:

#include
#include 
#include 

#include"myshm.h"

int main()
{
	int shmid = createShm(4096);

	char* addr = shmat(shmid,NULL,0);
	sleep(2);
	int i = 0;
	while(i++<26){
		printf("client say#%s\n",addr);
		sleep(1);
	}
	shmdt(addr);
	sleep(2);
	destoryShm(shmid);
	printf("myshm is destoryed\n");
	return 0;
}

client.c文件:

#include 

#include "myshm.h"

int main()
{
	int shmid = getShm(4096);

	char* addr = shmat(shmid,NULL,0);
	int i = 0;
	while(i<26)
	{
		addr[i] = 'A'+i;
		i++;
		addr[i] = '\0';
		sleep(1);
	}
	sleep(1);
	shmdt(addr);
	sleep(1);
	return 0;
}

运行结果截图:
进程间通信—— 共享内存_第3张图片

以上就是我们的共享内存的总结。
 Tip:限于编者水平,文章难免有缺漏之处,欢迎指正
   如需转载请注明出处!

你可能感兴趣的:(Linux)