多进程间通信学习之共享内存

  • 共享内存:
  • 1、在内核中创建共享内存;
  • 2、进程1和进程2都能够访问到,通过这段内存空间进行数据传递;
  • 3、共享内存是所有进程间通信方式中效率最高不需要在内核中往返进行拷贝
  • 4、共享内存的内存空间大小是4KB的整数倍
  • 常用的接口函数:
  • 一、创建共享内存(shmget函数):
c 复制代码
	#include <sys/ipc.h>
	#include <sys/shm.h>
	int shmget(key_t key, size_t size, int shmflg);
	/*
	参数:
		    key:键值
		        key 通过ftok获取
		        IPC_PRIVATE:只能用于亲缘进程间的通信
		    size:共享内存的大小  PAGE_SIZE(4k)的整数倍
		    shmflg:共享的标志位
		        IPC_CREAT|0666 或 IPC_CREAT|IPC_EXCL|0666
	返回值:
		    成功 共享内存编号
		    失败 -1 重置错误码
	*/
  • 二、映射共享内存到当前的进程空间(shmat函数):
c 复制代码
	#include <sys/ipc.h>
	#include <sys/shm.h>
	void *shmat(int shmid, const void *shmaddr, int shmflg);
	/*
	参数:
		    shmid:共享内存编号
		    shmaddr:NULL,让系统自动分配
		    shmflg:共享内存操作方式
		        0    		  读写
		        SHM_RDONLY    只读
	返回值:
		    成功 指向共享内存的地址
		    失败 (void *)-1 重置错误码
	*/
  • 三、取消地址映射(shmdt函数):
c 复制代码
	#include <sys/ipc.h>
	#include <sys/shm.h>
	int shmdt(const void *shmaddr);
	/*
	参数:
		    shmaddr:指向共享内存的指针
	返回值:
		    成功 0
		    失败 -1 重置错误码
	*/
  • 四、控制共享内存(shmctl函数):
c 复制代码
	#include <sys/ipc.h>
	#include <sys/shm.h>
	int shmctl(int shmid, int cmd, struct shmid_ds *buf);
	/*
	参数:
		    shmid:共享内存编号
		    cmd:操作的命令码
		        IPC_STAT:获取
		        IPC_SET:设置
		        IPC_RMID:删除共享内存
		            标记要销毁的段。实际上,只有在最后一个进程将其分离之后 
		            (关联结构shmid_ds的shm_nattch成员为零时), 
		            段才会被销毁。
		            调用者必须是段的所有者或创建者,或具有特权。buf参数被忽略。
		    buf:共享内存属性结构体指针
	返回值:
			成功 0
			失败 -1 重置错误码
	*/
  • 示例代码:
  • 写端:
c 复制代码
	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	
	#include <sys/types.h>
	#include <sys/ipc.h>
	
	#include <sys/shm.h>
	#include <unistd.h>
	
	#define PIGE_SIZE 4*1024
	
	int main(int argc, char const *argv[])
	{
	    //获取键值
	    key_t key = ftok("/home/linux/work/MSG", 'k');
	    if(-1 == key)
	    {
	        perror("ftok error");
	        exit(1);
	    }
	    //创建共享内存
	    int shmid = shmget(key, 2*PIGE_SIZE,IPC_CREAT|0666);
	    if(-1 == shmid)\
	    {
	        perror("shmget error");
	        exit(1);
	    }
	    //映射共享内存
	    char *sh_addr = (char *)shmat(shmid, NULL, 0);
	    if((void *) -1 == sh_addr)
	    {
	        perror("shmat error");
	        exit(1);
	    }
	    //向共享内存中写入数据
	    while(1)
	    {
	        fgets(sh_addr,128,stdin);
	        sh_addr[strlen(sh_addr)-1] = '\0';
	        if(!strncmp(sh_addr,"quit",4))
	        {
	            break;
	        }
	    }
	    //取消映射
	    if(-1 == shmdt(sh_addr))
	    {
	        perror("shmdt error");
	        exit(1);
	    }
	    //删除共享内存
	    if(-1 == shmctl(shmid, IPC_RMID, NULL))
	    {
	        perror("shmctl error");
	        exit(1);
	    }
	    
	    return 0;
	}
  • 读端:
c 复制代码
	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	
	#include <sys/types.h>
	#include <sys/ipc.h>
	
	#include <sys/shm.h>
	#include <unistd.h>
	
	#define PIGE_SIZE 4*1024
	
	int main(int argc, char const *argv[])
	{
	    //获取键值
	    key_t key = ftok("/home/linux/work/MSG", 'k');
	    if(-1 == key)
	    {
	        perror("ftok error");
	        exit(1);
	    }
	    //创建共享内存
	    int shmid = shmget(key, 2*PIGE_SIZE,IPC_CREAT|0666);
	    if(-1 == shmid)\
	    {
	        perror("shmget error");
	        exit(1);
	    }
	    //映射共享内存
	    char *sh_addr = (char *)shmat(shmid, NULL, 0);
	    if((void *) -1 == sh_addr)
	    {
	        perror("shmat error");
	        exit(1);
	    }
	    while(1)
	    {
	        sleep(2);//防止刷屏
	        printf("%s\n",sh_addr);
	        if(!strncmp(sh_addr,"quit",4))
	        {
	            break;
	        }
	    }
	    //取消映射
	    if(-1 == shmdt(sh_addr))
	    {
	        perror("shmdt error");
	        exit(1);
	    }
	    //删除共享内存
	    if(-1 == shmctl(shmid, IPC_RMID, NULL))
	    {
	        perror("shmctl error");
	        exit(1);
	    }
	    return 0;
	}
  • 运行结果:
c 复制代码
	linux@ubuntu:~/work/MSG$ gcc w3.c -o w3
	linux@ubuntu:~/work/MSG$ ./w3
	hi
	hello
	china
	quit
	linux@ubuntu:~/work/MSG$ gcc r3.c -o r3
	linux@ubuntu:~/work/MSG$ ./r3
	hi
	hi
	hi
	hello
	china
	china
	china
	quit
	shmctl error: Invalid argument
  • 注意:
  • 不按4k的整数倍给shmget传参,分配时也是按4k的整数倍分配
相关推荐
java叶新东老师7 分钟前
Linux /proc/目录详解
linux·运维·服务器
Asu520219 分钟前
思途SQL学习 0729
数据库·sql·学习
Star在努力21 分钟前
15-C语言:第15~16天笔记
c语言·笔记·算法
CoovallyAIHub26 分钟前
工业质检新突破!YOLO-pdd多尺度PCB缺陷检测算法实现99%高精度
深度学习·算法·计算机视觉
gb421528726 分钟前
负载均衡算法中的加权随机算法
windows·算法·负载均衡
都给我30 分钟前
服务器中涉及节流(Throttle)的硬件组件及其应用注意事项
服务器·网络·express
xdlka1 小时前
C++初学者4——标准数据类型
开发语言·c++·算法
long_mingyue1 小时前
CVE-2022-46169漏洞复现
linux
go54631584651 小时前
大规模矩阵构建与高级算法应用
线性代数·算法·矩阵
吹个口哨写代码1 小时前
防止包含 XSS 攻击风险的内容提交成功
java·服务器·前端