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

  • 共享内存:
  • 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的整数倍分配
相关推荐
Huangjin007_几秒前
【Linux 系统篇(十五)】进程 (三) :进程状态深度详解
linux·运维
RisunJan6 分钟前
Linux命令-talk(终端实时对话)
linux·运维·服务器
NeilYuen15 分钟前
【vemory】高性能KV存储AOF方案设计
linux·c++·redis·缓存
整点bug16 分钟前
AI 运维该不该自动执行命令?
运维·ssh·openai
听取WA声一片(无恶意)20 分钟前
CSP-J/S 初赛图论完全讲义
算法·csp-s初赛·csp-j初赛
Brilliantwxx31 分钟前
【算法从零到千】【51-54】逆序对(分治+递归算法)
数据结构·算法·排序算法
LONGZETECH35 分钟前
无人机组装调试实训高损耗痛点分析与虚拟仿真教学落地方案
c语言·开发语言·架构·无人机
不懂的浪漫37 分钟前
吴恩达《AI Engineering Skills Map》译读:四项核心能力与持续学习底座
人工智能·学习
小星星闪亮登场40 分钟前
2026河南萌新联赛第四场--南阳理工学院
数据结构·算法·贪心算法·动态规划·哈希算法·广度优先
Kurisu_红莉栖41 分钟前
关于docker的使用心得
运维·docker·容器