目录
一、与共享内存相关的函数
1、shmget()函数的使用:
#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
-返回值:
失败:返回-1,并设置错误号
成功:>0,返回共享内存引用的ID,后面操作共享内存都是通过这个值。
2、shmat()函数的使用
void *shmat(int shmid,const void*shmaddr,int shmflg);
-功能:和当前的进程相关联
-参数:
-shmid:共享内存的标识(ID),由shmget返回值获取。
-shmaddr:申请的共享内存起始位置,指定NULL,内核指定;
-shmflg:对共享内存的操作
-读:SHM_RDONLY,必须要有读权限
-读写:0
-返回值:
成功:返回共享内存的首(起始)地址。失败(void *)-1.
3、shmdt()函数的使用
int shmdt(const void *shmaddr);
-功能:解除当前进程和共享内存的关联
-参数:
shmaddr:共享内存的首地址
-返回值:成功0,失败-1
4、shmctl()函数的使用
int shmctl(int shmid,int cmd,struct shmid_ms *buf);
-功能:删除共享内存,共享内存要删除才会消失,创建共享内存的将进行被销毁了
-参数:
-shmid:共享内存的ID
-cmd:要做的操作
-IPC_STAT:获取共享内存的当前状态
-IPC_SET:设置共享内存的状态
-IPC_RMID:标记共享内存被销毁
-buf:需要设置或者获取的共享内存的属性信息
-IPC_STAT:buf存储数据
-IPC_SET:buf中需要初始化数据,设置到内核中
-IPC_RMID:没有用,NULL;
5、ftok()函数的使用
key_t ftok(const char *pathname,int proj_id);
-功能:根据指定的路径名,和int值,生成一个共享内存的key;
-参数:
-pathname:指定一个存在的路径
/home/shirui/Desktop/shared/a.txt
-proj_id:int 类型的值,但是这系统调用只会使用1个字节
范围:0-255 一般指定一个字符'a'。
6、接下来用代码解释这些函数的意思:
首先往内存中写数据
//写
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main()
{
//1、创建共享内存
int shmid=shmget(100,1024,IPC_CREAT|0664);
//2、关联当前进程
void (*ptr)=shmat(shmid,NULL,0);
//3、往内存中写数据
char *buf="hello guy";
memcpy(ptr,buf,strlen(buf)+1);//将buf中的内容复制到ptr这个首地址中去,别忘了字符串的长度+1
printf("按一下继续!\n");
getchar();
//4、解除关联
shmdt(ptr);
//5、删除共享内存
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
紧接着去内存中读数据:
//去内存中读取数据
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main()
{
//1、创建共享内存
int shmid=shmget(100,1024,IPC_CREAT);
//2、关联当前进程
void (*ptr)=shmat(shmid,NULL,SHM_RDONLY);
//3、读取内存中的数据
printf("%s\n",(char *)ptr);
printf("按一下继续!\n");
getchar();
//4、解除关联
shmdt(ptr);
//5、删除共享内存
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
执行写文件:
执行读文件:
二、共享内存中出现的问题
问题1:操作系统如何知道一块共享内存被多少个进程关联?
-共享内存维护了一个结构体struct shmid_ds 这个结构体成员中有一个成员shm_nattach
-shm_nattach记录了关联的进程个数
问题2 :可以对共享内存进行多次删除shmctl嘛?
可以的,因为shmctl标记删除共享内存,不是直接删除
-什么时候真正删除呢?
当和共享内存关联的进程数为0的时候就真正被删除。
-当共享内存的key为0的时候,表示共享内存被标记删除了
如果一个进程和共享内存取消关联,那么这个进程就不能继续操作这个共享内存了。
三、共享内存和内存映射的区别:
1、共享内存可以直接创建,内存映射需要磁盘文件(匿名映射除外)
2、共享内存效率更高;
3、内存
所有的进程操作都是对同一块共享内存;
内存映射,每个进程在自己的虚拟地址空间中有一个独立的内存
4、数据安全
-进程突然退出
共享内存还存在
内存映射区消失
-运行进程的电脑死机、宕机了
数据存在共享内存中,没有了
内存映射区的数据,由于磁盘文件中的数据还在,所以内存映射区的数据还存在
5、生命周期
-内存映射区:进程退出,内存映射区销毁
-共享内存:进程退出,共享内存还在,标记删除(所有的关联进程数为0),或者关机
如果一个进程退出,会自动和共享内存进行取消关联。
以上就是关于共享内存的相关说明。