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

  • 共享内存:
  • 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的整数倍分配
相关推荐
kkkkkkkkk_12012 分钟前
【强化学习】07周博磊强化学习纲要学习笔记——第四课上
学习·强化学习
ChristXlx2 分钟前
Linux安装mysql(虚拟机适用)
linux·mysql
知星小度S5 分钟前
系统核心解析:深入操作系统内部机制——基础I/O探秘:文件描述符、重定向与Shell的I/O魔法(二)
linux·i/o
小周学学学6 分钟前
vcenter的SMB备份
运维·服务器·vmware·虚拟化
dragoooon3410 分钟前
[C++——lesson29.数据结构进阶——「AVL树」]
算法
碧海银沙音频科技研究院14 分钟前
论文写作word插入公式显示灰色解决办法
人工智能·深度学习·算法
软件测试大叔18 分钟前
CentOS 7.6 安装 nvtop 完整教程
linux·centos·性能监控
长沙京卓27 分钟前
【无人机算法】低空经济下无人机巡检检测识别算法(城市、林业、水利)
算法·无人机
qq_3106585128 分钟前
mediasoup源码走读(十二)——router
服务器·c++·音视频
hn小菜鸡29 分钟前
LeetCode 1971.寻找图中是否存在路径
算法·leetcode·职场和发展