共享内存
介绍共享内存之前我们先看一下键值。
什么是键值?
键值:
就是保证进程之间打开的通信的介质是同一个
linux的键值:
以某个数值打开一个文件所产生出来的
ID是固定的
比如说一个文件在/home/lyx/test/1.c
特定的函数:获取键值的函数
XXX(/home/lyx/test/1.c);
打开这个文件,返回的ID是一个定值不管你用哪个进程不管何时刻,你在整个Linux下打开这个文件返回的这个ID都是一定的
保证唯一性:
只要有唯一性
就可以利用这个唯一性
来创建消息队列、
两个进程都用这个ID创建/打开消息队列
很明显,两个进程必然是访问的一个消息队列
函数功能:保证进程打开的共享内存、消息队列、信号量集是同一个
函数头文件:
#include <sys/types.h>
#include <sys/ipc.h>
函数原型:
key_t ftok(const char *pathname, int proj_id);
函数参数:
char *pathname:你要参考的文件
proj_id :你要参考的ID号(0~255)
函数返回值:
返回你需要的键值
失败返回 -1
//获取一个参考文件的固定的ID
//ID固定产生唯一性
//产生唯一性
//就可以以此为媒介作为创建/打开某个通信介质的条件
接下来我们看一下关于共享内存的函数:
函数功能:创建一个共享内存
函数头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函数原型:int shmget(key_t key, size_t size, int shmflg);
函数参数:
key:键值->以ftok获得
0 -> 仅用于父子间进程
size:指定的空间大小字节
shmflg:跟权限码非常相似
IPC_CREAT|0777
//没有就创建
函数返回值:
成功的返回创建共享内存的ID
失败返回 -1
/***************************************/
共享内存的映射:
函数功能:往进程中映射一个特定的共享内存
函数头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函数原型:
void *shmat(int shmid, const void *shmaddr, int shmflg);
函数参数:
shmid:共享ID号
shmaddr :映射的地址
你可以指定一个地址
你也可以让系统指定
0
shmflg:0: 可读可写
SHM_RDONLY:共享内存只读
函数返回值:
返回这片空间映射的地址
共享内存:默认是没有阻塞的
相当于一个特别数组
这个数组大家都可以访问
/***********************************/
函数功能:解除映射一个已经映射的共享内存
函数头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函数原型:
int shmdt(const void *shmaddr);
函数参数:
shmaddr:就是已经被映射的地址
函数返回:
0 成功
-1 失败
/*****************************/
函数功能:控制一个共享内存
函数头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
函数原型:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
函数参数:
shmid:共享内存的ID号
cmd : 操作
获取属性---IPC_STAT
设置共享内存--IPC_SET
删除共享内存(最常用)-IPC_RMID
shmid_ds *buf:
如果获取属性
那么他就把属性存到结构体
如果设置:
操作结构体
如果删除:
直接填写NULL
演示代码
在父进程里面创建共享内存并且打开,然后向共享内存中写入一句话,子进程从共享内存中读出这句话
共享内存:
共享单车
公共厕所
多个人共用
多个进程可以共用
内存:
一个存储空间
牵扯到空间的东西一般都跟地址有关
共享内存就是一片地址
想要用共享内存:
*创建共享内存
*映射共享内存空间
*解除映射
*删除共享空间
超级全局变量(内存):
所有进程都可以调用
都可以改变
void Test_shm(void)
{
pid_t pd=0;
int shm_id;
char * shm_addr =NULL;
pd = fork();
if(pd > 0)//父进程
{
shm_id = shmget(ftok("./TEST/main.c",0),32,IPC_CREAT|0664);//创建
shm_addr = (char *)shmat(shm_id,(void *)0,0);//映射 可读可写
strcpy(shm_addr,"i am father\n");
shmdt(shm_addr);//解除映射共享内存
}else//子进程
{
sleep(1);
shm_id = shmget(ftok("./TEST/main.c",0),32,IPC_CREAT|0664);/打开
shm_addr = (char *)shmat(shm_id,(void *)0,0);//映射 可读可写
printf("son: %s\n",shm_addr);
shmdt(shm_addr);//解除映射共享内存
shmctl(shm_id,IPC_RMID,NULL);//删除共享内存
}
}
演示结果: