文章目录
- 一、共享内存
- 二、案例实现
- 总结
一、共享内存
共享存储允许两个或多个进程共享一给定的存储区。因为数据不需要在客户机和服务器之间复制,所以这是最快的一种 I P C。使用共享存储的唯一窍门是多个进程之间对一给定存储区的同步存取。若服务器将数据放入共享存储区,则在服务器做完这一操作之前,客户机不应当去取这些数据。通常,信号量被用来实现对共享存储存取的同步。
常用函数
#include<sys/ipc.h>
#include<sys/shm.j>
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,后面操作共享内存都是通过这个值
void *shmat(int shmid, const void *shmaddr, int shmflg);
-功能:和当前的进程进行关联
-参数:
-shmid:共享内存的标识(ID),由shmget返回值获取
-shmaddr:申请的共享内存的起始地址,指定为NULL,内核指定
-shmflg:对共享内存的操作
-读:SHM_RDONLY,必须要有读权限
-读写:0
-返回值:
成功:返回共享内存的首地址。
失败: (void*)-1。
int shmdt(const void *shmaddr);
-功能:解除当前进程和共享内存的关联
-参数:
shmaddr:共享内存首地址
-返回值:
成功 0
失败 -1
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
-功能:删除共享内存,共享内存要删除才会消失,创建共享内存的进行被销毁了对共享内存是没有任何影响的
-参数:
-shmidi:共享内存的ID
-cmd:要做的操作
-IPC_STAT:获取共享内存的当前的状态
-IPC_SET:设置共享内存的状态
-IPC_RMID:标记共享内存被销毁
-buf:需要设置或者获取的共享内存的属性信息
-IPC_STAT:buf存储数据
-IPC_SET:buf中需要初始化数据,设置到内核中
-IPC_RMID:没有用,NULL
key_t ftok(const char *pathname, int proj_id);
-功能:根据指定的路径名,和int值,生成一个共享内存的key
-参数:
-pathname:指定一个存在的路径
/home/daima/a.txt
-proj_id:int类型的值,但是这系统调用只会使用其中一个字节
范围:0-255 一般指定一个字符 'a'
常见问题
问题1:操作系统如何知道一块共享内存被多少进程关联?
-共享内存维护了一个结构体struct shmid_ds 这个结构体中有一个成员 shm_nattch
-shm_nattch 记录了关联的进程个数
问题2:可不可以对共享内存进行多次删除shmctl
-可以的
-因为shmctl只是标记共享内存,不是直接删除
-什么时候真正删除呢?
当和共享内存关联的进程数为0的时候,就真正被删除
-当共享内存被标记删除了,标识共享内存被标记删除了
如果一个进程和共享内存取消关联,那么这个进程就不能继续操作这个共享内存了
共享内存和内存映射的区别
1.共享内存可以直接创建,内存映射需要磁盘文件(匿名映射除外)
2.共享内存效率更高
3.内存
所有的进程操作的是同一块共享内存
内存映射,每个进程在自己的虚拟地址空间中有一个独立的内存。
4.数据安全
-进程突然退出
共享内存区还存在
内存映射区消失
-运行进程的电脑宕机了
数据存储在共享内存中,就没有了
内存映射区的数据,由于磁盘文件中的数据还在,所有内存映射区的数据还存在。
5.生命周期
-内存映射区:进程退出,内存映射区销毁
-共享内存:进程退出,共享内存还在,手动删除(所有关联的进程数为0),或者关机。
如果一个进程退出,会自动和共享内存取消关联。
二、案例实现
write_shm.c
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>
int main()
{
//1.创建一个共享内存
int shmid = shmget(100,4096,IPC_CREAT|0664);
printf("shmid:%d\n",shmid);
//2.和当前进程进行关联
void* ptr = shmat(shmid,NULL,0);
//3.写数据
char* str="hello world";
memcpy(ptr,str,strlen(str)+1);
printf("按任意键继续\n");
getchar();
//4.解除关联
shmdt(ptr);
//5.删除共享内存
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
read_shm.c
#include<stdio.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<string.h>
int main()
{
//1.获取一个共享内存
int shmid = shmget(100,0,IPC_CREAT);
printf("shmid:%d\n",shmid);
//2.和当前进程进行关联
void* ptr = shmat(shmid,NULL,0);
//3.读数据
printf("%s\n",(char*)ptr);
printf("按任意键继续\n");
getchar();
//4.解除关联
shmdt(ptr);
//5.删除共享内存
shmctl(shmid,IPC_RMID,NULL);
return 0;
}
总结
今天主要给大家介绍了共享内存,主要用于进程间的通信,其速度相对于其他进程通信要快很多。