有了之前的学习经验,共享内存对我们学习起来相对简单一些了,这里简单说说共享内存的一些,然后对于函数的分析直接在代码里面的注释部分有说明,如果还是不懂,可以先看看前面的关于IPC–信号量还有IPC–消息队列的讲解
共享内存以传递数据为目的,速度最快,不需要数据在内存还物理内存的来回的拷贝,直接访问访问虚拟地址空间
共享内存没有同步与互斥机制,这个时候我们可以结合着IPC–信号量进行进程间通信
下面我们直接粘贴代码
client.c
#include"comm.h"
int main()
{
int shmid = getShm(0);
int i = 0;
char* arr = (char*)shmat(shmid,NULL,0);
while(1)
{
sleep(1);
printf("%s\n",arr);
i++;
if(i==25)
break;
}
int dt = shmdt(arr);
if(dt < 0)
{
perror("shmdt\n");
return -1;
}
return 0;
}
comm.c
#include"comm.h"
static int commShm(int size,int flag) //size:共享内存的大小,flag:进行何种操作,是获取还是创建
{
key_t key = ftok(PATHNAME,ID);
if(key < 0)
{
perror("key_t\n");
return -1;
}
int shmid = shmget(key,size,flag); //key:键值,size:大小,这里传入的大小最好是4k(4096)的倍数
//因为4096是一页,如果我们传递的是4097,系统会自动的对齐到8192,
//但是因为我们申请的是4097,剩下的内存系统不会给你,flag:创建方式
if(shmid < 0)
{
perror("shmget\n");
return -2;
}
return shmid;
}
int creatShm(int size) //size:创建内存空间的大小
{
return commShm(size,IPC_CREAT|IPC_EXCL|0666);
}
int getShm(int size)
{
return commShm(size,IPC_CREAT); //size:默认设置为0
}
int desShm(int shmid)
{
int des = shmctl(shmid,IPC_RMID,NULL); //shmid:删除的是哪一个共享内存,IPC_RMID:控制方式,这里是删除的意思
//NULL:这里是struct shmid_ds *buf,这是一个维护共享 内存的一个结构体
//暂时不关心
if(des < 0)
{
perror("shmctl\n");
return -1;
}
return des;
}
comm.h
#ifndef _COMM_H_
#define _COMM_H_
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#define PATHNAME "."
#define ID 0x6666
int creatShm(int size);
int getShm(int size);
int desShm(int shmid);
#endif
server.c
#include"comm.h"
int main()
{
int i = 0;
int shmid = creatShm(27);
char* arr = (char*)shmat(shmid,NULL,0); //这里可以把shmat当成是malloc使用,shmid:信号量标识符
//NULL:const void* shmaddr,虚拟地址空间,设置为NULL,这个是系统自己定义的
//返回值void* 这个时候我们要强制转换成我们需要的类型
for(;i<26;)
{
sleep(1);
arr[i] = 'A' + i; //这里可以直接当成是malloc开辟的一个数组使用
i++;
arr[i] = 0;
}
int dt = shmdt(arr); //arr:这个就是我们上面的那个内存空间地址
if(dt < 0)
{
perror("shmdt\n");
return -1;
}
desShm(shmid);
return 0;
}