【共享内存】共享内存(Shared Memory)与进程通信
目录
一、共享内存概述
共享内存允许两个或者多个进程共享给定的存储区域。
共享内存的特点:
1)共享内存是进程间共享数据的一种最快的方法。
一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。
2)使用共享内存要注意的是多个进程之间对一个给定存储区域访问的互斥。
若一个进程正在向共享内存区写数据,则在它做完这一步操作前,别的进程不应当去读、写这些数据。
共享内存示意图:
共享内存是进程间通信方式中效率最高的,原因在于进程是直接在物理内存上进行操作,将物理地址映射到用户进程这,所以只要对其地址进行操作,就是直接对物理地址操作。
二、共享内存操作
在ubuntu12.04中共享内存限制如下:
- 共享存储区的最小字节数:1
- 共享存储区的最大字节数:32M
- 共享内存区的最大个数:4096
- 每个进程最多能映射的共享存储区的个数:4096
使用shell命令操作共享内存:
查看共享内存:ipcs -m
删除共享内存:ipcrm -m shmid
1)获得一个共享存储标识符:shmget函数
shmget函数:
#include<sys/ipc.h>
#include<sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:创建一个共享内存
参数:
key:键值,唯一的键值确定唯一的共享内存
size:创建的共享内存的大小
shmflg:共享内存的访问权限
一般为IPC_CREAT | 0777
返回值:
成功:共享内存的id
失败:-1
代码示例:
#include<sys/ipc.h>
#include<sys/shm.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
printf("shmid = %d\n", shmid);
system("ipcs -m");
return 0;
}
执行截图:
2)共享内存映射(attach):shmat函数
shmat函数:
#include<sys/types.h>
#include<sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:映射共享内存
参数:
shmid:共享内存的id
shmaddr:映射的地址,设置为NULL为系统自动分配
shmflg:标志位
0:共享内存具有可读可写权限
SHM_RDONLY:只读
返回值:
成功:映射的地址
失败:-1
3)解除共享内存映射(detach):shmdt函数
shmdt函数:
#include<sys/types.h>
#include<sys/shm.h>
int shmdt(const void *shmaddr);
功能:
解除共享内存的映射
参数:
shmaddr:映射的地址,shmat的返回值
返回值:
成功:0
失败:-1
共享内存映射与解除内存映射代码案例:
write.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
int main()
{
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
char* text;
if ((text = shmat(shmid, NULL, 0)) == (void*)-1)
{
perror("fail to shmat");
exit(1);
}
//写入
strcpy(text, "hello world");
if (shmdt(text) == -1)
{
perror("fail to text");
exit(1);
}
system("ipcs -m");
return 0;
}
read.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
int main()
{
//创建共享内存
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
// system("ipcs -m");
//映射
char* text;
if ((text = shmat(shmid, NULL, 0)) == (void*)-1)
{
perror("fail to shmat");
exit(1);
}
printf("text = %s\n", text);
//解除映射
if (shmdt(text) == -1)
{
perror("fail to shmdt");
exit;
}
system("ipcs -m");
return 0;
}
执行截图:
4)共享内存控制:shmctl函数
shmctl函数:
#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:共享内存的属性结构体
返回值:
成功:0
失败:-1
代码示例:
#include<stdlib.h>
#include<unistd.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main()
{
key_t key;
if ((key = ftok(".", 100)) == -1)
{
perror("fail to ftok");
exit(1);
}
int shmid;
if ((shmid = shmget(key, 500, IPC_CREAT | 0666)) == -1)
{
perror("fail to shmget");
exit(1);
}
printf("shmid = %d\n", shmid);
//删除共享内存
if (shmctl(shmid, IPC_RMID, NULL) == -1)
{
perror("fial to shmid");
exit(1);
}
system("ipcs -m");
return 0;
}
执行截图:
总结:
共享内存作为一种高效的进程间通信机制,以其独特的优势在多进程环境中发挥着重要的角色。它允许多个进程直接访问同一块内存区域,从而实现了数据的快速共享和交换,显著提高了系统性能。然而,这也带来了数据同步和并发控制的挑战。我们需要结合锁、信号量等同步技术来解决这些问题。
总的来说,共享内存是一种强大而灵活的工具,但需要谨慎、有效地使用,以确保程序的正确性和稳定性。
更多推荐
所有评论(0)