Linux学习记录(十二)————共享内存


5.共享内存

1.概念

共享内存(Shared Memory)就是允许多个进程访问同一个内存空间,是在多个进程之间共享和传递数据最 高效的方式。操作系统将不同进程之间共享内存安排为同一段物理内存,进程可以将共享内存连接到它们自 己的地址空间中,如果某个进程修改了共享内存中的数据,其它的进程读到的数据也将会改变。

  • 共享内存指令
    • ipcs -m-------查看
    • ipcrm -m shmid------删除
2.相关函数
1.int shmget(key_t key, size_t size, int shmflg);
//用来获取或创建共享内存
/*
*@param:
*		key:IPC_PRIVATE 或 ftok的返回值
*		size:共享内存区大小
*		shmflg:同open函数的权限位,也可以用8进制表示法
*@return:成功:共享内存段标识符‐‐‐ID‐‐‐文件描述符,出错:‐1
*/


2.int shmctl(int shm_id, int command, struct shmid_ds *buf);
//删除共享内存对象
/*
*@return:
*		shmid:要操作的共享内存标识符
*		cmd :
*			IPC_STAT (获取对象属性)‐‐‐ 实现了命令ipcs ‐m
*			IPC_SET (设置对象属性)
*			IPC_RMID (删除对象) ‐‐‐实现了命令ipcrm ‐m
*		buf :指定IPC_STAT/IPC_SET时用以保存/设置属性
*返回值:成功:0,出错:‐1
*/
    
注:
	若参数key为IPC_PRIVATE-----key值为0,方便有亲缘关系的进程间的通信

特点:

  • 1.共享内存创建之后,一直存在于内核中,直到被删除或系统关闭

  • 2.共享内存和管道不一样,读取后,内容仍然在共享内存中

创建和删除共享内存

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>

int main()
{
        int shmid;
        shmid = shmget(IPC_PRIVATE,128,0777);
        if(shmid == -1)
        {
                printf("creat share memory failed\n");
                return -1;
        }
        printf("creat share memory successed\n");
        system("ipcs -m");
        shmctl(shmid,IPC_RMID,NULL);
        system("ipcs -m");
        return 0;
}

在这里插入图片描述

共享内存映射

Linux共享内存映射(Shared Memory Mapping)是一种让进程之间通过内存直接交换数据的技术。它有以下几个显著的好处:

  • 效率高:共享内存避免了频繁的数据复制,因为数据直接存储在内核空间的物理地址上,读写速度通常比基于文件或网络通信快。

  • 低开销:映射操作相对轻量级,不像socket通信需要建立连接,减少了系统资源消耗。

  • 实时性:由于数据在不同进程间是直接访问的,这使得共享内存适用于对时间敏感的应用场景,如嵌入式系统、游戏引擎等。

  • 协作方便:多个进程可以同时修改同一块共享内存,这对于需要协同工作的进程非常有用,比如多线程或者多进程间的协同计算。

  • 易于同步:通过信号量、互斥锁等机制,可以更容易地控制对共享内存的访问,保证数据的一致性。

2.void *shmat(int shm_id, const void *shm_addr, int shmflg);
//把共享内存连接映射到当前进程的地址空间
/*
 *@param:
 *	shm_id:ID号
 *	shm_addr:映射到的地址,NULL为系统自动完成的映射
 *	shmflg:
 *		SHM_RDONLY共享内存只读
 *		默认是0,表示共享内存可读写
 *@return:成功:映射后的地址,失败:NULL
 */
3.int shmdt(const void *shmaddr);
//将进程里的地址映射删除
/*
 *@return:
 *shmid:要操作的共享内存标识符
 *@return:成功:0,出错:‐1
 */

注:共享内存中的数据读取之后仍存在!

共享内存映射

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
int main()
{
	int shmid;
	key_t key;
	char *p;
	key = ftok("a.c",1);	
	if(key == -1)
	{
		printf("create key failed\n");
		return -2;
	}
	printf("creat key successed key is %x\n",key);
	shmid = shmget(key,128,IPC_CREAT|0777);
	if(shmid == -1)
	{
		printf("create share memory failed\n");
		return -1;
	}
	printf("creat share memory successed of shmid is %d\n",shmid);
	system("ipcs -m");
	p = (char *)shmat(shmid,NULL,0);
	if(p == NULL)
	{
		printf("create share memory Mapping failed\n ");
	}
	//write 
	fgets(p,128,stdin);
	//read
	printf("share memory Mapping is %s\n",p);
	printf("Second share memory Mapping is %s\n",p);
	shmdt(p);
	shmctl(shmid,IPC_RMID,NULL);
	system("ipcs -m");
	return 0;
}

在这里插入图片描述

ipcrm -m shmid实现

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <string.h>
int main(int argc,char * argv[])
{
	int shmid;
	if(argc != 3)
	{
		printf("param error\n");
		return -1;
	}
	if(strcmp(argv[1],"-m") == 0)
	{
		printf("delete share memory");
	}
	else
	{
		printf("error");
		return -2;
	}
	shmid = atoi(argv[2]);
	shmctl(shmid,IPC_RMID,NULL);
	system("ipcs -m");
	return 0;
}

在这里插入图片描述

共享内存进程间的通信

思路:一个收一个发

//shm_write
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
	int shmid;
	key_t key;
	char *p;
	key = ftok("a.c",1);	
	if(key == -1)
	{
		printf("create key failed\n");
		return -2;
	}
	printf("creat key successed key is %x\n",key);
	shmid = shmget(key,128,IPC_CREAT|0777);//创建共享内存
	if(shmid == -1)
	{
		printf("create share memory failed\n");
		return -1;
	}
	printf("creat share memory successed of shmid is %d\n",shmid);
	system("ipcs -m");
	p = (char *)shmat(shmid,NULL,0);//获取共享内存映射地址
	if(p == NULL)
	{
		printf("create share memory Mapping failed\n ");
	}
	//write 
	fgets(p,128,stdin);
	sleep(8);
	shmdt(p);
	shmctl(shmid,IPC_RMID,NULL);
	return 0;
}
//shm_read
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
int main()
{
	int shmid;
	key_t key;
	char *p;
	key = ftok("a.c",1);//获取key值
	if(key == -1)
	{
		printf("create key failed\n");
		return -2;
	}
	printf("creat key successed key is %x\n",key);
	shmid = shmget(key,128,0);//不创建新的共享内存只借助Key值获取shmid
	if(shmid == -1)
	{
		printf("create share memory failed\n");
		return -1;
	}
	printf("creat share memory successed of shmid is %d\n",shmid);
	system("ipcs -m");
	p = (char *)shmat(shmid,NULL,0);//获取p的地址
	if(p == NULL)
	{
		printf("create share memory Mapping failed\n ");
	}
	//read
	printf("share memory Mapping is %s\n",p);
	shmdt(p);
	return 0;
}

在这里插入图片描述

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值