一、共享内存是什么?
共享内存允许两个或更多进程访问同一块内存,不同进程之间共享的内存通常为计算机中的同一段物理内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。进程可以将同一段物理内存连接到他们自己的地址空间中(通过虚拟地址映射),所有的进程都可以访问共享内存中的地址。
共享内存的优缺点:
原文链接:https://blog.csdn.net/d_guco/article/details/53524854
1.共享内存号称是最快的进程间通信方式。
2.共享内存适用于大数据量的传输,读取不等待写入,需要设置同步,可以用信号量来实现对共享内存同步访问控制。可以通过管道发送同步信号。管道适合传输小数据量。
3.通过名字知道它是基于内存的,所以他只能在同一主机上使用,如果我们要做分布式应用或者跨物理机通信,那么socket就是我们唯一的选择了。
二、书写代码时的可能出现的错误
-
向共享内存中存放数据时,需在共享内存映射之后再存放数据,否则存放不成功
-
存放数据时若出现段错误时,则可能是因为代码中出现了野指针
-
若两个进程中开辟的共享内存空间不一致则报错:shmget: Invalid argument
三、代码例程
参考知乎了知乎上的代码例程
情景:创建两个进程,在 A 进程中创建一个共享内存,并向其写入数据(结构体形式进行数据传输 ),通过 B 进程从共享内存中读取数据
A写进程:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define BUFSZ 100
struct Mem{
int type ;
char data[BUFSZ];
};
int main(int argc, char *argv[])
{
//struct Mem mem1;
int shmid;
int ret;
key_t key;
struct Mem *shmadd;
//创建key值
key = ftok("/dev/ppp", 2021);
if(key == -1)
{
perror("ftok");
}
//创建共享内存
shmid = shmget(key, BUFSZ*sizeof(char)+sizeof(int), IPC_CREAT|0666);
if(shmid < 0)
{
perror("shmget");
exit(-1);
}
//映射
shmadd = (struct Mem *)shmat(shmid, NULL, 0);
if(shmadd < 0)
{
perror("shmat");
_exit(-1);
}
// 共享内存清空
memset(shmadd, 0, sizeof(shmadd));
//拷贝数据至共享内存区
printf("copy data to shared-memory\n");
//bzero(mem1.data, BUFSZ); // 共享内存清空
(*shmadd).type = 1;
strcpy((*shmadd).data, "how are you, lh\n");
//拷贝数据至共享内存区
//printf("copy data to shared-memory\n");
//strcpy(shmadd, "how are you, lh\n");
printf("type = [%d]\n", (*shmadd).type);
printf("data = [%s]\n", (*shmadd).data);
return 0;
}
B读进程:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define BUFSZ 100
typedef struct MemA{
int type;
char data[BUFSZ];
}MemA;
int main(int argc, char *argv[])
{
int shmid;
int ret;
key_t key;
MemA *shmadd;
//创建key值
key = ftok("/dev/ppp", 2021);
if(key == -1)
{
perror("ftok");
}
system("ipcs -m"); //查看共享内存
//打开共享内存
shmid = shmget(key, BUFSZ +4, IPC_CREAT|0666);
if(shmid < 0)
{
printf("error");
perror("shmget");
exit(-1);
}
//映射
shmadd = (MemA *)shmat(shmid, NULL, 0);
if(shmadd < 0)
{
perror("shmat");
exit(-1);
}
//读共享内存区数据
printf("type = [%d]\n", (*shmadd).type);
printf("data = [%s]\n", (*shmadd).data);
//分离共享内存和当前进程
ret = shmdt(shmadd);
if(ret < 0)
{
perror("shmdt");
exit(1);
}
else
{
printf("deleted shared-memory\n");
}
//删除共享内存
shmctl(shmid, IPC_RMID, NULL);
system("ipcs -m"); //查看共享内存
return 0;
}
提示:
代码中所用到的函数详情可参考链接: https://cloud.tencent.com/developer/article/1527533.
总结
1.实现数据以结构体形式进行进程之间通信。
2.代码未提供同步机制