目录
一、原理(共享内存效率最高)
操作内存通过一个内存将两个进程作为共享的区域,则两个进程可以直接访问一块内存,效率提高。
共享内存一般要配合信号量、互斥锁等协调机制,让各个进程再高效交换数据的同时,不会发生数据践踏、破坏等意外。
二、思想
进程与进程之间虚拟内存空间原本是相互独立、不能互相访问
共享内存是通过某些方式,使得同一块物理内存多次映射到不同的进程虚拟空间之中
三、使用共享内存的一般步骤
1、获取共享内存对象的ID
2、将共享内存映射至本进程虚拟内存空间的某个区域
3、当不再使用时,解除映射关系
4、当没有进程再需要这块共享内存时,删除它
四、共享内存(SHM)的API
1、 shmget(获取共享内存的ID)
2、shmat(映射贡献内存)、shmdt(解除映射)
3、shmctl(获取或者设置共享内存的相关属性)
- IPC_RMID当所有都解除映射之后,才删除
- SHM_LOCK不是锁定读写权限,而是锁定SHM能否与swap分区发生交换。若被设置了,则任何访问这个SHM的进程都将会遇到页错误。
- 进程可以通过IPC_STAT后得到的mode来检测SHM_LOCKED信息
- swap分区:硬盘空间不是内存空间
- swap分区在系统的物理内存不够时,把硬盘内内存中的一部分空间释放处理啊,以供当前运行的程序使用,释放的空间可能来自一些很长事件没有什么操作的程序,这些被释放的空间被临时保存到swap分区中,等程序运行时,再从swap分区中回复保存的数据到内存中
五、写入数据(write代码)
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main(int argc, char const *argv[])
{
// 获得key值
int key = ftok("./" , 'K');
// 通过key值获得ID
int id = shmget( key , 4096 , IPC_CREAT | 0666 );
// 映射共享内存
char * shm_map = shmat(id , NULL , SHM_RND );//映射内存
if ( shm_map == (char *)-1 )
{
perror("shmat error");
return -1 ;
}
// 为所欲为
memcpy(shm_map , "Hello GZ2123", sizeof("Hello GZ2123"));
printf("拷贝成功!!!");
return 0;
}
六、读出数据(read代码)
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
int main(int argc, char const *argv[])
{
// 获得key值
int key = ftok("./" , 'K');
// 通过key值获得ID
int id = shmget( key , 4096 , IPC_CREAT | 0666 );
// 映射共享内存
char * shm_map = shmat(id , NULL , SHM_RND );
if ( shm_map == (char *)-1 )
{
perror("shmat error");
return -1 ;
}
printf("共享内存的内容:%s\n" , shm_map );
return 0;
}
七、共享内存+信号捕获
(1)写入
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
// 获得key值
int key = ftok("./" , 'K');
// 通过key值获得ID
int id = shmget( key , 4096 , IPC_CREAT | 0666 );
// 映射共享内存
char * shm_map = shmat(id , NULL , SHM_RND );
if ( shm_map == (char *)-1 )
{
perror("shmat error");
return -1 ;
}
// 为所欲为
int pid = *(int*)shm_map ;
printf("对方pid :%d \n" , pid );
while(1)
{
fgets(shm_map , 128 , stdin);
// memcpy(shm_map , "Hello GZ2123", sizeof("Hello GZ2123"));
printf("拷贝成功!!!\n");
kill( pid , 3 );
if( strstr(shm_map , "bye-bye"))
{
break ;
}
}
// 解除映射
shmdt(shm_map);
// 标记删除
shmctl( id , IPC_RMID , NULL );
return 0;
}
(2)读取
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
int id;
char * shm_map ;
void read_msg( int sig )
{
printf("共享内存的内容:%s\n" , shm_map );
if( strstr(shm_map , "bye-bye"))
{
// 解除映射
shmdt(shm_map);
// 标记删除
shmctl( id , IPC_RMID , NULL );
exit( 1 );
}
return ;
}
int main(int argc, char const *argv[])
{
signal( 3 , read_msg );
// 获得key值
int key = ftok("./" , 'K');
// 通过key值获得ID
id = shmget( key , 4096 , IPC_CREAT | 0666 );
// 映射共享内存
shm_map = shmat(id , NULL , SHM_RND );
if ( shm_map == (char *)-1 )
{
perror("shmat error");
return -1 ;
}
// 为所欲为
int pid = getpid();
printf("我的ID:%d\n" ,pid );
memcpy(shm_map , &pid , sizeof(int));
// printf("拷贝成功!!!");
while(1)
{
pause();
}
return 0;
}