共享内存(效率最高的进程间通信方式)
共享内存简单实现
写
/*
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
-功能:创建一个新的共享段,或者获取一个既有的共享内存段的标识
新创建的内存段中的数据都会被初始化为0
-参数:
-key: key_t是整形,通过这个找到或者创建一个共享内存,一般使用16进制的非0值
-size: 也是个整形,共享内存的大小,分页的整数倍
-shmflg: 属性:访问权限/附加属性:创建/判断共享内存是否存在
-IPC_CREAT:创建
-IPC_EXCL: 判断共享内存是否存在,需要和IPC_CREAT一起使用(IPC_CREAT | IPC_EXCL | 0664)
-SHM_HUGETLB:不常用
-SHM_HUGE_2MB:不常用
-返回值:
-成功: >0的值,表示共享内存引用的ID
-失败: -1,并且设置错误号
===============================================================================================================\
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
-功能:和当前的进程进行关联
-参数:
-shmid:共享内存的标识ID,即shmget的返回值
-shmaddr:申请的共享内存的起始地址,指定NULL,由内核指定。
-shmflg:对共享内存的操作
-不指定(0):读写
-SHM_EXEC:
-SHM_RDONLY:读,必须要有读权限
-SHM_REMAP:
-返回值:
-成功:返回共享内存的首地址
-失败:(void *)-1;
int shmdt(const void *shmaddr);
===============================================================================================
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
-功能: 解除当前进程和共享内存的关联
-参数:
-shmaddr:共享内存的首地址
-返回值:
-成功:0
-失败:-1
==============================================================================================
#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: 标记共享内存被销毁
-buf:需要设置或者获取的共享内存的属性信息
-IPC_STAT:buf存储数据
-IPC_SET: buf中需要初始化数据,设置到内核中
-IPC_RMID: 没有用(NULL)
*/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
int main(){
//创建共享内存
int shmID = shmget(100, 4096, IPC_CREAT|0664);
printf("shmID = %d\n", shmID);
if(shmID == -1){
perror("shmget");
return -1;
}
//关联
void *addr = shmat(shmID, NULL, 0);
if(addr == (void *)-1){
perror("shmat");
return -1;
}
//进行操作:写数据
char buff[1024] = "hello this is share A \n";
memcpy(addr, buff, sizeof(buff));
printf("按任意键继续 \n");
getchar();
//解除关联
shmdt(addr);
//删除共性内存
shmctl(shmID, IPC_RMID, NULL);
return 0;
}
读
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
int main(){
//创建共享内存
int shmID = shmget(100, 0, IPC_CREAT);
printf("shmID = %d\n", shmID);
if(shmID == -1){
perror("shmget");
return -1;
}
//关联
void *addr = shmat(shmID, NULL, 0);
if(addr == (void *)-1){
perror("shmat");
return -1;
}
//进行操作:读数据
printf("%s",(char*)addr);
printf("按任意键继续。。。。。。\n");
getchar();
//解除关联
shmdt(addr);
//删除共性内存
shmctl(shmID, IPC_RMID, NULL);
return 0;
}
相关问题
/*
问题1: 操作系统如何知道一块共享内存被多少个进程关联?
-共享内存维护了一个结构体struct shmid_ds这个结构体中有一个成员shm_attch记录了关联的进程个数
-共享内存的键变为0表示标记删除,因为还有进程和他关联,当没有进程关联时删除
问题2:是否可以对共享内存进行多次删除shmctl
-可以,shmctl是标记删除,只有当关联数为0时才被真正删除
问题3:共享内存和内存映射的区别
-共享内存可以直接创建,内存映射需要磁盘文件(匿名映射除外)
-共享内存效率更高
-内存:
-共享内存:所有的进程操作的是同一块内存
-内存映射:每个进程在自己的虚拟地址空间中有一个独立的内存
-数据安全:
-进程突然退出:
-共享内存还存在
-内存映射区消失
-运行进程的电脑死机:
-数据存储在共享内存中就没了
-内存映射区中的数据由于磁盘文件中的数据还在,所以内存映射区的数据还存在
-生命周期:
-共享内存:进程退出,共享内存还在,手动删除(所有的关联都没了)或者关机才销毁
如果一个进程退出,会自动和共享内存取消关联。
-内存映射:进程退出,内存映射区销毁
*/