Linux 进程间通信--共享内存深度解析

本文详细介绍了Linux系统V共享内存的概念、使用函数(shmget、shmat、shmdt、shmctl)及其参数,提供了一个简单的客户端和服务端通信的示例代码,展示了如何创建、连接、脱离和控制共享内存。共享内存是高效的进程间通信方式,通过key值查找同一资源,使用ipcrm命令可以删除共享内存。
摘要由CSDN通过智能技术生成

system V共享内存

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。进行多个进程间通信

在这里插入图片描述

共享内存函数

shmget函数
功能:用来创建共享内存
原型:
int shmget(key_t key, size_t size, int shmflg);
参数
key:这个共享内存段名字
size:共享内存大小
shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回-1
shmat函数
功能:将共享内存段连接到进程地址空间
原型
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数
shmid: 共享内存标识
shmaddr:指定连接的地址
shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY
返回值:成功返回一个指针,指向共享内存第一个节;失败返回-1
shmaddr为NULL,核心自动选择一个地址
shmaddr不为NULL且shmflg无SHM_RND标记,则以shmaddr为连接地址。
shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的
整数倍。公式:shmaddr -
(shmaddr % SHMLBA)
shmflg=SHM_RDONLY,表示连接操作用来只读共享内存
shmdt函数
功能:将共享内存段与当前进程脱离
原型
int shmdt(const void *shmaddr);
参数
shmaddr: 由shmat所返回的指针
返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段
shmctl函数
功能:用于控制共享内存
原型
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数
shmid:由shmget返回的共享内存标识码
cmd:将要采取的动作(有三个可取值)
buf:指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回0;失败返回-1

在这里插入图片描述

实例代码

# ls
client.c comm.c comm.h Makefile server.c
# cat Makefile
.PHONY:all
all:server client
client:client.c comm.c
gcc -o $@ $^
server:server.c comm.c
gcc -o $@ $^
.PHONY:clean
clean:
rm -f client server

comm.h

#ifndef COMM_H #define COMM_H
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define PATHNAME "."
#define PROJ_ID 0x6666
int createShm(int size);
int destroyShm(int shmid);
int getShm(int size);
#endif

comm.c

#include "comm.h"
static int commShm(int size, int flags)
{
	key_t _key = ftok(PATHNAME, PROJ_ID);//设定一个K值
	if(_key < 0){
	perror("ftok");
	return -1;
}
int shmid = 0;
if( (shmid = shmget(_key, size, flags)) < 0)//创建一个共享内存,并以K命名
{
	perror("shmget");
	return -2;
}
return shmid;//成功返回共享内存段的标识符
}
int destroyShm(int shmid)
{
	if(shmctl(shmid, IPC_RMID, NULL) < 0)//IPC_RMID删除命令
	{
	perror("shmctl");
	return -1;
	}
	return 0;
}
int createShm(int size)
{
	return commShm(size, IPC_CREAT|IPC_EXCL|0666);
	//IPC资源生命周期随内核
}
int getShm(int size)
{
	return commShm(size, IPC_CREAT);
}

server.c

#include "comm.h"
int main()
{
	int shmid = createShm(4096); 
	char *addr = shmat(shmid, NULL, 0);//挂接
	sleep(2);
	int i = 0;
	while(i++<26)
	{
		printf("client# %s\n", addr);
		sleep(1);
	}
	shmdt(addr);//取消挂接
	sleep(2);
	destroyShm(shmid);//自动删除共享内存
	return 0;
}

client.c

#include "comm.h"
int main()
{
	int shmid = getShm(4096);
	sleep(1);
	char *addr = shmat(shmid, NULL, 0);
	sleep(2);
	int i = 0;
	while(i<26)
	{
		addr[i] = 'A'+i;
		i++;
		addr[i] = 0;
		sleep(1);
	}
	shmdt(addr);
	sleep(2);
	return 0;
}

结果:
在这里插入图片描述

//共享内存实质上通过Key值找到同一个资源

ipc -m   //查看共享内存
ipcrm -m  shmid  //删除共享内存
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值