进程间通信方式——共享内存「建议收藏」

进程间通信方式——共享内存「建议收藏」进程间通信方式共享内存和与共享内存函数详解,以及模拟共享内存实现进程间通信,以及共享内存的优缺点。

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

1.什么是共享内存?

共享内存就是允许两个或多个进程共享一定的存储区。就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。因为数据不需要在客户机和服务器端之间复制,数据直接写到内存,不用若干次数据拷贝,所以这是最快的一种IPC。
注:共享内存没有任何的同步与互斥机制,所以要使用信号量来实现对共享内存的存取的同步。
进程间通信方式——共享内存「建议收藏」

2.与共享内存有关的数据结构

system V版本的通信方式都具有相似的数据结构,参考见:


注:其中的同只是将数据结构中的消息队列msg换成shm而已

3.与共享内存有关的函数

所有的函数共用头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

3.1创建共享内存——>shmget() 函数

int shmget(key_t key, size_t size, int shmflg);
				//成功返回共享内存的ID,出错返回-1        


(1)第一个参数key是长整型(唯一非零),系统建立IPC通讯 ( 消息队列、 信号量和 共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到,由内核变成标识符,要想让两个进程看到同一个信号集,只需设置key值不变就可以。

 (2)第二个参数size指定共享内存的大小,它的值一般为一页大小的整数倍(未到一页,操作系统向上对齐到一页,但是用户实际能使用只有自己所申请的大小)。

 (3)第三个参数shmflg是一组标志,创建一个新的共享内存,将shmflg 设置了IPC_CREAT标志后,共享内存存在就打开。而IPC_CREAT | IPC_EXCL则可以创建一个新的,唯一的共享内存,如果共享内存已存在,返回一个错误。一般我们会还或上一个文件权限

3.2操作共享内存———>shmctl()函数

int shmctl(int shm_id, int cmd, struct shmid_ds *buf); 
				//成功返回0,出错返回-1


(1)第一个参数,shm_id是shmget函数返回的共享内存标识符。

(2)第二个参数,cmd是要采取的操作,它可以取下面的三个值 :    

IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。    

IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值    

IPC_RMID:删除共享内存段

(3)第三个参数,buf是一个结构指针,它指向共享内存模式和访问权限的结构。 shmid_ds结构至少包括以下成员 

struct shmid_ds  
{  
    uid_t shm_perm.uid;  
    uid_t shm_perm.gid;  
    mode_t shm_perm.mode;  
};        


3.3挂接操作———>shmat()函数


创建共享存储段之后,将进程连接到它的地址空间

void *shmat(int shm_id, const void *shm_addr, int shmflg); 
					//成功返回指向共享存储段的指针,出错返回-1

(1)第一个参数,shm_id是由shmget函数返回的共享内存标识。


(2)第二个参数,shm_addr指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。

(3)第三个参数,shm_flg是一组标志位,通常为0

3.4分离操作———>shmdt()函数

该操作不从系统中删除标识符和其数据结构,要显示调用shmctl(带命令IPC_RMID)才能删除它

int shmdt(const void *shmaddr); //成功返回0,出错返回-1

(1)addr参数是以前调用shmat时的返回值

4.模拟实现进程间的通信方式———>共享内存

Server作为发送方,每次向共享内存中,写入A,Client作为接收方,每次读取共享内存中的数据

comm.h

#ifndef __COMM_H__
#define __COMM_H__
#include <stdio.h>
#include <error.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define PATHNAME "."
#define PROJ_ID 066
int CreatShmid(int size);
int GetShmid(int size);
int Destory(int shmid);
#endif

comm.c

#include "comm.h"
static int commShmid(int size,int flag)
{
    key_t key=ftok(PATHNAME,PROJ_ID);
    if(key>0)
    {   
        return shmget(key,size,flag);
    }   
    else
    {   
        perror("ftok");
        return -1; 
    }   
}

int CreatShmid(int size)
{
    return commShmid(size,IPC_CREAT|IPC_EXCL|0666);
}
int GetShmid(int size)
{
    return commShmid(size,IPC_CREAT);
}
int Destory(int shmid)
{
    return shmctl(shmid,0,IPC_RMID);
}

server.c

#include "comm.h"
int main()
{
    int shmid=CreatShmid(4097);
    if(shmid>0)
    {   
        int i=0;
        char *addr=shmat(shmid,NULL,0);
        while(i<20)
        {   
            addr[i++]='A';
            addr[i]='\0';
            sleep(1);
        }   
        if(shmdt(addr)==-1)
        {   
            perror("shmat");
            return -3; 
        }   

    }   
   else
    {   
        perror("CreatShmid");
        return -1;
    }
    if(Destory(shmid)<0)
    {
        perror("Destory");
        return -2;
    }
    return 0;
}
 

client.c

#include "comm.h"
int main()
{
    int shmid=GetShmid(4097);
    if(shmid>0)
    {   
        int i=0;
        char *addr=shmat(shmid,NULL,0);
        while(i<20)
        {   
            printf("%s\n",addr);
            sleep(1);
            i++;
        }   
        if(shmdt(addr)==-1)
        {   
            perror("shmdt");
            return-1;
        }   
    }   
    else
    {   
        perror("GetShmid");
      return -2;
    }
    return 0;
}


进程间通信方式——共享内存「建议收藏」


通过查看共享内存状态可以知道操作系统提供给用户的共享内存为4097个字节,实际上操作系统开辟了8K个字节,而且由于接收方client还没挂接,所以挂接数为1。


运行结果:
进程间通信方式——共享内存「建议收藏」

运行结果分析:


共享内存中的数据并不会像管道或者信号量等被一端读取之后就不存在。

5.使用共享内存的优缺点

优点:我们可以看到使用共享内存进行进程间的通信真的是非常方便,而且函数的接口也简单,数据的共享还使进程间的数据不用传送,而是直接访问内存,也加快了程序的效率。同时,它也不像匿名管道那样要求通信的进程有一定的父子关系(system V版本共有)。

缺点:共享内存没有提供互斥同步的机制,这使得我们在使用共享内存进行进程间通信时,往往要借助其他的手段比如信号量等来进行进程间的同步工作。 



其他进程间通信方式详解:











































版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/183818.html原文链接:https://javaforall.net

(0)
上一篇 2022年8月31日 下午1:46
下一篇 2022年8月31日 下午2:00


相关推荐

  • LabelImg安装

    LabelImg安装LabelImg安装

    2022年6月17日
    30
  • dual channel ddr3主板_ddr3 std

    dual channel ddr3主板_ddr3 std第一次看到ODT这个东西,真是一头雾水;然后是TerminationRank,FAE解释了几次,也没明白。究其原因,这玩意儿和硬件太相关,而不是纯粹软件的TRUEorFALSE。好歹也是通信工程毕业,号称软硬通吃,怎能被轻易难倒?ODT,全称OnDieTermination。我们先说Termination的概念。一个DDR通道,通常会挂接多个Rank,这些Rank的数

    2025年10月15日
    3
  • Vue 定时器/定时调用

    Vue 定时器/定时调用前端定时器;定时调用方法;间隔重复调用

    2025年7月2日
    8
  • pycharm 远程开发

    pycharm 远程开发1 服务器安装图形化和 pycharm 本地使用 MobaXterm 工具登陆 session 配置勾选 x11 forwarding 运行 pycharm sh2 本地 pycharm 远程服务器的同步配置远程服务器 IP 地址 192 168 203 95 开启 ssh 服务 安装 python 版本 2 7 我用一个在 PyCharm 里面的 core python 项目来做演示 首

    2026年3月17日
    2
  • 常见NoSQL数据库概述

    常见NoSQL数据库概述我们再日常的运维中 应用及接触最多无疑是关系型数据库了 尤其以开源的为主 Mysql MariaDB Postgrelsql 等 然后随着业务的复杂 数据量及类型的快速转变 我们不得不考虑更多数据库满足我们的业务需要 必须时序性的 全文检索的 k v 的 即时查询的 图形的 音视频的等等 作为运维 我们也不得不了解并掌握其中最常用的典型代表

    2026年3月17日
    1
  • 从“卖API”到“卖解决方案” 月之暗面Kimi押注Agent|聚焦

    从“卖API”到“卖解决方案” 月之暗面Kimi押注Agent|聚焦

    2026年3月12日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号