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

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

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • vue删除对象的某个属性(js怎么删除对象中的某个元素)

    微信小程序开发交流qq群173683895承接微信小程序开发。扫码加微信。实现代码:vardata={a:1,b:2,c:3}for(varitemindata){if(item==’b’){deletedata[item];}}console.log(‘data:…

    2022年4月11日
    46
  • finsh AJax

    finsh AJax2019独角兽企业重金招聘Python工程师标准>>>…

    2022年5月11日
    30
  • ideavim有什么用_intellij idea社区版

    ideavim有什么用_intellij idea社区版IdeaVim史诗级分享之前就对vim非常着迷,而我本身就是写java代码的,经常使用Idea这个IDE。2019年初,Idea里一个和vim有关的插件,深深的吸引了我,名字叫Ideavim。后来我就开始使用了。用它的时候,idea原本的快捷键很多就会失去自己的效力。需要进行重新映射,我花了一些时间将一些非常常用的快捷键整理收集,然后赋予其ideavim的快捷键。取得了非常不错的效果。使用vim,最大的好处,是减少打代码的时候进行键鼠切换的频率。有一种相当不错流畅感

    2022年10月1日
    0
  • Java方法重写与重载的区别

    Java方法重写与重载的区别Java方法重写与重载一、方法重写(0veriding)在Java程序中,类的继承关系可以产生一个子类,子类继承父类,它具备了父类所有的特征,继承了父类所有的方法和变量。子类可以定义新的特征,当子类需要修改父类的一些方法进行扩展,增大功能,程序设计者常常把这样的一种操作方法称为重写,也叫称为覆写或覆盖。重写体现了Java优越性,重写是建立在继承关系上,它使语言结构更加丰富。在J…

    2022年7月8日
    28
  • zigbee开发板(nxpzigbee开发)

    前面我们搭建好了zigbee开发的硬件平台,买一块开发板,注意只要这块开发板上有cc2530,可以向里面烧录程序就可以了。具体的烧录过程我会最近上传我的烧录过程,相关软件我尽快上传。好了回归这一次的主题,那么我们到底需要什么样的开发环境呢?这完全取决于你的项目大小,如果你的项目只是学会使用zigbee,那么你只需要一款烧录软件,以及一款合适的用于编写cc2530的c编译器就OK了。但是我这

    2022年4月10日
    54
  • 克隆节点的方法_手机克隆phone

    克隆节点的方法_手机克隆phone<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8&quo

    2022年8月4日
    5

发表回复

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

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