进程间通信——共享内存
进程间通信的方式有信号量,消息队列,管道,今天我们学习进程间通信的另外一种通信方式:共享内存
共享内存有一个最大的特点就是:以传送数据为目的,在所有进程间通信方式中速度最快的。
进程间通信的方式有信号量,消息队列,管道,今天我们学习进程间通信的另外一种通信方式:共享内存
共享内存有一个最大的特点就是:以传送数据为目的,在所有进程间通信方式中速度最快的。
原因就是管道消息队列等通信方式,都是在临界资源写好数据之后,读方不读的时候,是不知道写方写入了哪些数据的,
所以就需要拷贝两份数据,但是共享内存是将数据写到物理内存的时候,读方就立刻看到写入的数据。
共享内存原理图:
关于共享内存,系统对于共享内存和消息队列和信号量一样也有一个对应的结构体,如下:
共享内存的原理就是,让两个进程关联到同一块物理内存,这样读方和写方都可以直接操作,就减少进行数据的拷贝
关于共享内存的创建,需要知道以下几个函数:
①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 <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#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<stdio.h>
#include <sys/types.h>
#include <sys/shm.h>
#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 <stdio.h>
#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;
}
运行结果截图:
以上就是我们的共享内存的总结。
Tip:限于编者水平,文章难免有缺漏之处,欢迎指正
如需转载请注明出处!