【Linux】IPC通信之共享内存

本文详细介绍了Linux系统中的共享内存通信,包括共享内存的概念、相关函数接口如shmget、shmat、shmdt、shmctl的使用,以及如何通过代码实现共享内存通信。此外,还探讨了共享内存的特点,如高效性、生命周期与内核相关以及其在SystemV IPC中的角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

共享内存概念

共享内存指的是,在多处理器的计算机系统中,可以被不同的CPU访问大量内存。由于多个CPU需要快速访问存储器,所以必须对存储器进行缓存。在缓存中的数据被更新后,其他处理器也可能要进行读取,共享内存就需要立即更新,否则不同的处理器将读取到不同的数据。共享内存是Unix、Linux下多进程通信的一种方式之一,这种方法通常用于一个程序的多进程间通信。实际上多个进程可以通过共享内存来进行通信

有关函数接口

与共享内存有关的接口有四个:shmget,shmat,shmdt,shmctl

 头文件<sys/shm.h>

              <sys/types.h>

              <sys/ipc.h>

进行共享内存的获取

int shmget(key_t key, size_t size, int shmflg)

参数

size 以页表为基本单位,是4k的整数倍(4096);

IPC_CREAT:当shmflg&IPC_CREAT为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共

内存的标识符 

将进程挂载到共享内存

void *shmat(int shmid, const void *shmaddr, int shmflg)
参数

shmaddr指定共享内存出现在进程内存地址的什么位置

将共享内存上的进程删除

int shmdt(const void *shmaddr)

shmaddr:连接的共享内存的地址

删除共享内存

int shmctl(int shmid, int cmd, struct shmid_ds *buf)

参数

cmd为IPC_RMID销毁共享内存

buf共享内存管理结构体

代码实现共享内存

comm.h

#ifndef __SHM_H__
#define __SHM_H__

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

#define PATHNAME "."
#define	PROJ_ID 0x666

int CreatShm(int size);//创建共享内存
int GetShm(int size);//获取已有的共享内存
char* AtShm(int shmid);//将进程号为 shmid 的进程 挂到共享内存上
int DtShm(char* addr);//将指向addr的共享内存上的进程移除
int Destroy(int shmid);//释放共享内存

#endif

comm.c

#include"comm.h"

//创建共享内存和获取共享内存的公共代码
static int commShm(int flag, int size)
{
	key_t _key = ftok(PATHNAME, PROJ_ID);
	if(_key < 0)
	{
		perror("ftok");
		return -1;
	}

	int shmid = shmget(_key , size, flag);
	if(shmid < 0)
	{
		perror("shmget");
		return -2;
	}
	return shmid;
}

//创建共享内存
int CreatShm(int size)
{
	return commShm(IPC_CREAT|IPC_EXCL|0666,size);
}

//获取已存在的共享内存
int GetShm(int size)
{
	return commShm(IPC_CREAT,size);
}

//将进程号为size的进程挂到共享内存中
char* AtShm(int shmid)
{
	//void* shmat(int shmid, const void* shmaddr, int shmflg);
	return (char*)shmat(shmid, NULL,0);
}

//将共享内存的进程移除
int DtShm(char* addr)
{
	//int shmdt(const void* shmaddr);
	return shmdt(addr);
}

//销毁共享内存
int DestroyShm(int shmid)
{
	//int shmctl(int shmid,int cmd,struct shmid_ds *buf);
	if(shmctl((shmid),IPC_RMID,NULL)<0)
	{
		perror("shmctl");
		return -1;
	}
	return 0;
}

client.c

#include"comm.h"

int main()
{
	int shmid = GetShm(4096);//获取共享内存
	char* addr = AtShm(shmid);//将进程挂载到共享内存
	if(addr == NULL)//检测挂载是否成功
	{
		printf("addr == NULL\n");
	}
	int i = 0;
	while(i < 4095)
	{
		addr[i] = 'a';//每次多写入一个a
		addr[i+1] = '\0';//
		sleep(1);//休眠1秒
		i++;
	}
	DtShm(addr);//将进程从共享内存上移除
	DestroyShm(shmid);//销毁共享内存
	return 0;
}

server.c

#include"comm.h"

int main()
{	
	int shmid = CreatShm(4096);//创建共享内存
	char* addr = AtShm(shmid);//挂载到共享内存
	if(addr == NULL)
	{
		printf("NULL\n");
	}

	while(1)
	{
		sleep(1);
		printf("%s\n",addr);
	}
	DtShm(addr);//将共享内存上的进程移除
	DestroyShm(shmid);//删除共享内存
	return 0;
}

makefile文件

.PHONY:all
all:server client
server:server.c comm.c
	gcc -o $@ $^
client:client.c comm.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -f server client

运行结果


共享内存的特点

1、共享内存是进程间通信最快的

2、共享内存的生命周期是随内核的

3、共享内存是属于SystemV通信的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值