共享内存对象:(SHM)
操作框架:
key值==》申请对象==》挂载对象==》读写对象==》卸载对象 ==》删除对象
shmget() shmat() 内存读写 shmdt() shmctl()
1、申请对象
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:该函数使用公共key值向内核提出共享内存使用申请;
参数: key 唯一键值
size 要申请的共享内存大小
shmflg 申请方式和权限,第一次 IPC_CREAT
判断是否存在用 IPC_EXCL;
返回值:成功 返回一个有效的shmid表示消息队列对象id
失败 -1;
2、挂载对象(映射对象)
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:该函数可以将已经申请成功的共享内存挂载到本地进程的
私有空间地址上。
参数: shmid 共享内存id
shmaddr 当前进程的可读写、空闲、同等大小 的内存挂载地址;
NULL 表示由系统自动查找合适区域并挂载;
shmflg 挂载到本地的内存读写权限;
返回值:成功 返回已经挂载成功的本地内存
失败 NULL
3、读写共享内存:所有的io读写方式都可以,对于共享内存的读写可以
借鉴malloc堆区内存的读写方式;
练习:
使用共享内存完成 父子进程间的 数字 字符串 结构体 三种
不同数据信息的进程间通信;
注意:共享内存挂载成功后,操作的内存在本地,目标内存在共享区域
但是内存的所有操作一定要借鉴堆区内存。
4、卸载共享内存 ( 断开映射 )
int shmdt(const void *shmaddr);
功能:该函数用于卸载之前已经挂载的共享内存;
参数:shmaddr 要断开的地址
返回值:成功 0
失败 -1;
注意:使用完毕尽量将指针归零 shmaddr = NULL;
5、删除共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:该函数用于修改共享内存的属性,可以用于删除共享内存;
参数:shmid 共享内存id
cmd IPC_RMID 表示删除共享内存对象
buf NULL 表示属性不做调整;
返回值:成功 0
失败 -1;
//共享内存写内存
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
struct shmbuf
{
int a;
char b;
};
int main()
{
key_t key;
if((key=ftok(".",'m'))<0)
{
perror("ftok error\n");
return -1;
}
int shmid;
struct shmbuf *shm;
if((shmid=shmget(key,512,IPC_CREAT|IPC_EXCL|0664))<0)
{
if(errno!=EEXIST)
{
perror("shmget error\n");
return -1;
}
else
{
shmid=shmget(key,512,0664);
}
}
if((shm=shmat(shmid,NULL,0))!=NULL)
{
printf("shm=%p\n",shm);
}
//写内存
shm->a=10;
shm->b='q';
if(shmdt(shm)<0)
{
perror("shmdt error\n");
return -1;
}
system("ipcs -m");
return 0;
}
//共享内存读内存
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
struct shmbuf
{
int a;
char b;
};
int main()
{
key_t key;
if((key=ftok(".",'m'))<0)
{
perror("ftok error\n");
return -1;
}
int shmid;
struct shmbuf *shm;
if((shmid=shmget(key,512,IPC_CREAT|IPC_EXCL|0664))<0)
{
if(errno!=EEXIST)
{
perror("shmget error\n");
return -1;
}
else
{
shmid=shmget(key,512,0664);
}
}
if((shm=shmat(shmid,NULL,0))!=NULL)
{
printf("shm=%p\n",shm);
}
//读内存
printf("a=%d b=%c\n",shm->a,shm->b);
if(shmdt(shm)<0)
{
perror("shmdt error\n");
return -1;
}
shmctl(shmid,IPC_RMID,NULL);
system("ipcs -m");
return 0;
}