精华内容
下载资源
问答
  • C++共享内存进程间通信 FileMapping用于进程间快速通信
  • 实验系统:Windows10 ...简介:使用MFC,实现了进程间通信共享内存的方式。在实验中,我建立了两个MFC工程,相当于两个进程,进程之间可以进行双向的通信,不过只实现了字符串的数据形式,但是值得学习。
  • http://blog.csdn.net/ezhchai/article/details/74992980文章中讲解的示例程序完整工程文件
  • 代码实现了共享内存和信号量的结合,实现进程间通信及其同步问题。通过此代码可以理解共享内存及信号量基本函数的使用及实现原理。
  • 第 5 章 System V 进程间通信 1 2 System V IPC 基础 消息队列 3 信号量通信机制 4 共享内存 信号量基本概念 ? 信号量是操作系统中解决进程或线程同步与互斥的最重要机 制之一 Linux 内核提供 System V 的信号量机制...
  • 主要为大家详细介绍了Python进程间通信共享内存的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 采用共享内存实现进程间通信。方便实在,代码中忘了释放资源了,下载后的同学记得释放掉共享内存。很实用。
  • C#进程间通信-共享内存代码实例

    热门讨论 2013-12-04 08:03:58
    C#进程间通信-共享内存代码实例。用实现了2个进程,他们之间使用共享内存方式进行通信。
  • 分为3个工程:proA,proB,ShareMemLib 其中proA,proB是用wpf写的两个模拟进程程序 ShareMemLib将共享内存代码封装成lib,定义了发送者和监听者 两个进程在实例化Share...至此成功完成了两个进程间通过共享内存实现通信
  • 因为数据不需要在各个进程之间复制,所以这是最快的一种进程间通信方式。使用共享内存时的关键点在于如何在多个进程之间对一给定的存储区进行同步访问。  例如若一个进程正在将数据放入共享内存区,则在它做完这一...
  • 利用共享内存实现进程间通信,可用于操作系统的教学。(原创)
  • VC用共享内存实现进程间通信

    热门讨论 2012-01-11 14:58:05
    C++ 用共享内存实现进程间通信 所用IDE为VS2003
  • Windows进程间通信共享内存

    热门讨论 2013-05-13 21:02:09
    共享内存方式实现进程间通信。详细看我的博客:http://blog.csdn.net/pengguokan/article/details/8921346
  • 自己做的一个ppt通过共享内存的方式实现进程间通信
  • 进程间通信——共享内存(Shared Memory)

    万次阅读 多人点赞 2018-04-16 16:19:17
    共享内存是System V版本的最后一个进程间通信方式。共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存...

    共享内存是System V版本的最后一个进程间通信方式。共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一段物理内存连接到他们自己的地址空间中,所有的进程都可以访问共享内存中的地址。如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。

    特别提醒:共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前,并无自动机制可以阻止第二个进程开始对它进行读取,所以我们通常需要用其他的机制来同步对共享内存的访问,例如信号量

    下面就 Shared Memory 的IPC作以阐述与分析。

    共享内存的通信原理

    Linux中,每个进程都有属于自己的进程控制块(PCB)地址空间(Addr Space),并且都有一个与之对应的页表,负责将进程的虚拟地址与物理地址进行映射,通过内存管理单元(MMU)进行管理。两个不同的虚拟地址通过页表映射到物理空间的同一区域,它们所指向的这块区域即共享内存

    共享内存的通信原理示意图:

    对于上图我的理解是:当两个进程通过页表将虚拟地址映射到物理地址时,在物理地址中有一块共同的内存区,即共享内存,这块内存可以被两个进程同时看到。这样当一个进程进行写操作,另一个进程读操作就可以实现进程间通信。但是,我们要确保一个进程在写的时候不能被读,因此我们使用信号量来实现同步与互斥。

    对于一个共享内存,实现采用的是引用计数的原理,当进程脱离共享存储区后,计数器减一,挂架成功时,计数器加一,只有当计数器变为零时,才能被删除。当进程终止时,它所附加的共享存储区都会自动脱离。

    为什么共享内存速度最快?

    借助上图说明:Proc A 进程给内存中写数据, Proc B 进程从内存中读取数据,在此期间一共发生了两次复制

    (1)Proc A 到共享内存       (2)共享内存到 Proc B

    因为直接在内存上操作,所以共享内存的速度也就提高了。

    共享内存的接口函数以及指令

    1.查看系统中的共享存储段

    ipcs -m

    2.删除系统中的共享存储段

    ipcrm -m [shmid]

    3.shmget ( ):创建共享内存

    int shmget(key_t key, size_t size, int shmflg);

    [参数key]:由ftok生成的key标识,标识系统的唯一IPC资源。

    [参数size]:需要申请共享内存的大小。在操作系统中,申请内存的最小单位为页,一页是4k字节,为了避免内存碎片,我们一般申请的内存大小为页的整数倍。

    [参数shmflg]:如果要创建新的共享内存,需要使用IPC_CREAT,IPC_EXCL,如果是已经存在的,可以使用IPC_CREAT或直接传0。

    [返回值]:成功时返回一个新建或已经存在的的共享内存标识符,取决于shmflg的参数。失败返回-1并设置错误码。

    4.shmat ( ):挂接共享内存

    void *shmat(int shmid, const void *shmaddr, int shmflg);

    [参数shmid]:共享存储段的标识符。

    [参数*shmaddr]:shmaddr = 0,则存储段连接到由内核选择的第一个可以地址上(推荐使用)。

    [参数shmflg]:若指定了SHM_RDONLY位,则以只读方式连接此段,否则以读写方式连接此段。

    [返回值]:成功返回共享存储段的指针(虚拟地址),并且内核将使其与该共享存储段相关的shmid_ds结构中的shm_nattch计数器加1(类似于引用计数);出错返回-1。

    5.shmdt ( ):去关联共享内存

    当一个进程不需要共享内存的时候,就需要去关联。该函数并不删除所指定的共享内存区,而是将之前用shmat函数连接好的共享内存区脱离目前的进程。

    int shmdt(const void *shmaddr);

    [参数*shmaddr]:连接以后返回的地址。

    [返回值]:成功返回0,并将shmid_ds结构体中的 shm_nattch计数器减1;出错返回-1。

    6.shmctl ( ):销毁共享内存

    int shmctl(int shmid, int cmd, struct shmid_ds *buf);

    [参数shmid]:共享存储段标识符。

    [参数cmd]:指定的执行操作,设置为IPC_RMID时表示可以删除共享内存。

    [参数*buf]:设置为NULL即可。

    [返回值]:成功返回0,失败返回-1。

    模拟共享内存

    我们用server来创建共享存储段,用client获取共享存储段的标识符,二者关联起来之后server将数据写入共享存储段,client从共享区读取数据。通信结束之后server与client断开与共享区的关联,并由server释放共享存储段。

    comm.h

    //comm.h
    #ifndef _COMM_H__
    #define _COMM_H__
    
    #include<stdio.h>
    #include<sys/types.h>
    #include<sys/ipc.h>
    #include<sys/shm.h>
    
    #define PATHNAME "."
    #define PROJ_ID 0x6666
    
    int CreateShm(int size);
    int DestroyShm(int shmid);
    int GetShm(int size);
    #endif
    

    comm.c

    //comm.c
    #include"comm.h"
    
    static int CommShm(int size,int flags)
    {
    	key_t key = ftok(PATHNAME,PROJ_ID);
    	if(key < 0)
    	{
    		perror("ftok");
    		return -1;
    	}
    	int shmid = 0;
    	if((shmid = shmget(key,size,flags)) < 0)
    	{
    		perror("shmget");
    		return -2;
    	}
    	return shmid;
    }
    int DestroyShm(int shmid)
    {
    	if(shmctl(shmid,IPC_RMID,NULL) < 0)
    	{
    		perror("shmctl");
    		return -1;
    	}
    	return 0;
    }
    int CreateShm(int size)
    {
    	return CommShm(size,IPC_CREAT | IPC_EXCL | 0666);
    }
    int GetShm(int size)
    {
    	return CommShm(size,IPC_CREAT);
    }
    

    client.c

    //client.c
    #include"comm.h"
    
    int main()
    {
    	int shmid = GetShm(4096);
    	sleep(1);
    	char *addr = shmat(shmid,NULL,0);
    	sleep(2);
    	int i = 0;
    	while(i < 26)
    	{
    		addr[i] = 'A' + i;
    		i++;
    		addr[i] = 0;
    		sleep(1);
    	}
    	shmdt(addr);
    	sleep(2);
    	return 0;
    }
    

    server.c

    //server.c
    #include"comm.h"
    
    int main()
    {
    	int shmid = CreateShm(4096);
    
    	char *addr = shmat(shmid,NULL,0);
    	sleep(2);
    	int i = 0;
    	while(i++ < 26)
    	{
    		printf("client# %s\n",addr);
    		sleep(1);
    	}
    	shmdt(addr);
    	sleep(2);
    	DestroyShm(shmid);
    	return 0;
    }

    Makefile

    //Makefile
    .PHONY:all
    all:server client
    
    client:client.c comm.c
    	gcc -o $@ $^
    server:server.c comm.c
    	gcc -o $@ $^
    
    .PHONY:clean
    clean:
    	rm -f client server
    

    运行结果:


    总结:

    (1)优点:我们可以看到使用共享内存进行进程之间的通信是非常方便的,而且函数的接口也比较简单,数据的共享还使进程间的数据不用传送,而是直接访问内存,加快了程序的效率。

    (2)缺点:共享内存没有提供同步机制,这使得我们在使用共享内存进行进程之间的通信时,往往需要借助其他手段来保证进程之间的同步工作。


    展开全文
  • 进程间通讯(即:同机通讯)和数据交换有多种方式:消息、共享内存、匿名(命名)管道、邮槽、Windows套接字等多种技术。“共享内存”(shared memory)可以定义为对一个以上的进程是可见的内存或存在于多个进程的虚拟...
  • QT间进程通信共享内存

    热门讨论 2013-12-09 15:42:50
    比如说QQ的聊天的客户端,这里有个个性头象,当点击QQ音乐播放器的时候,启动QQ音乐播放(启动一QQ音乐播放器的进程)这时QQ音乐播放器里也有一个个性头像,这两者的头像一样,现用共享内存的方法实现。
  • 通过COM组件封存共享内存的方法,并添加到注册表,成为一个共享内存的服务。任何一个进程只要使用这个...方便不同进程间通信,增加了通信效率。但是慎用这种方法,该方法已经在WINDOWS7下通过测试,XP下有时候会弹错。
  • Qt共享内存实现进程间通信(QSharedMemory) 源代码
  • 进程间通信---共享内存

    千次阅读 2018-03-30 23:42:10
    前边说过,进程间通信的实质就是让两个不相干的进程看到同一份公共的资源,而内存是资源的一种,那么,如果让两个进程可以使用同一块内存,两个进程都可以往这块内存里边写东西和取东西,这不就是实现了进程间的通信...

           前边说过,进程间通信的实质就是让两个不相干的进程看到同一份公共的资源,而内存是资源的一种,那么,如果让两个进程可以使用同一块内存,两个进程都可以往这块内存里边写东西和取东西,这不就是实现了进程间的通信了么。通过共享内存实现进程间的通信,原理很简单,主要就是它的实现了。

           每个进程都具有自己独立的地址空间,又怎么让两个进程共享同一块内存呢?我们都知道,给进程的地址空间其实都是虚拟地址,然后操作系统会根据进程的实际需要才给进程分配合适的物理内存(将虚拟地址映射到物理地址空间中去),那么问题就好解决了,只要两个进程映射到同一块物理内存空间不就行了?但是映射的过程是由操作系统完成与控制,怎么让属于不同进程的两块虚拟地址空间映射到同一块内存空间呢?


    系统提供了几个函数来帮助我们实现以上过程。掌握了这几个函数,也就相当于掌握了共享内存。

    shmget函数  ---创建

    功能:用于创建共享内存
    原型:int  shmget(key_t key,size_t size,int shmflg)
    参数:key:这个共享内存段的名字
      size:共享内存的大小
      shmflg:由九个权限标志构成,其用法跟创建文件时使用的mode模式标志一样。

    返回值:成功返回一个非负整数,即该共享内存段的标志码;失败返回-1

    shmat函数 ---连接

    功能:将共享内存连接到进程地址空间
    原型:void* shmat (int shmid, const void* shmaddr, int shmflg)
    参数:shmid:共享内存标识
      shmaddr:指定连接的地址
      shmflg:它的两个可能取值分别是SHM_RND和SHM_RDONLY

    返回值:成功返回一个指针,指向共享内存的第一节;失败返回-1

    说明:

    shmaddr为NULL,内核⾃动选择⼀个地址
    shmaddr不为NULL且shmflg⽆SHM_RND标记,则以shmaddr为连接地址。
    shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会⾃动向下调整为SHMLBA的整数倍。
    公式:shmaddr - (shmaddr % SHMLBA)shmflg=SHM_RDONLY,表⽰连接操作⽤来只读共享内存

    可能有人会有所疑问,为什么要先创建一块共享内存然后再将其与一个进程的地址空间连接起来呢?如果将创建内存空间和连接合为一步,那么这么做另一个进程就不能连接到这块空间了。有时候我们希望进程A跟进程B共享内存结束后,会希望进程A再跟进程C共享这块内存,这个时候就需要将进程B从这块共享内存中脱离下来(当然,同一块共享内存是可以同时有多个进程连接的)。系统也为我们提供了这样一个用于脱离的函数

    shmdt函数 ---脱离

    功能:将共享内存段与当前进程脱离
    原型:int shmdt(const void *shmaddr);
    参数:shmaddr: 由shmat所返回的指针
    返回值:成功返回0;失败返回-1

    注意:将共享内存段与当前进程脱离不等于删除共享内存段

    内存是一种宝贵的资源,用完一定要记得还回去。

    shmctl函数 ---控制

    功能:⽤于控制共享内存
    原型:int shmctl (int shmid, int cmd, struct shmid_ds* buf);
    参数:shmid:由shmget返回的共享内存标识码
              cmd:将要采取的动作(有三个可取值)
        buf:指向⼀个保存着共享内存的模式状态和访问权限的数据结构
    返回值:成功返回0;失败返回-1
    cmd的三个可取值:
    IPC_STAT:将shmid_ds结构中的数据设置为共享内存当前的关联值
    IPC_SET:在进程权限足够的条件下,将共享内存的当前关联值设置为shmid_ds数据结构中给出的值

    IPC_RMID:删除共享内存

    代码实例

    用于包含头文件和函数声明的comm.h部分

    #ifndef __COMM_H__
    #define __COMM_H__
    
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <stdlib.h>
    
    #define PATHNAME "."
    #define PROJ_ID 0x6666
    
    #define ERR_EXIT(n)\
    	do\
    	{\
    		perror(n);\
    		exit(EXIT_FAILURE);\
    	}while(0)
    
    int CreatShm(int size);
    int DestroyShm(int shm_id);
    int GetShm(int size);
    
    #endif
    用于定义公共函数(在server.c和client.c里边都会使用的函数)的comm.c部分
    #include "comm.h"
    
    static int Creat(int size,int flags)
    {
    	key_t key = ftok(PATHNAME,PROJ_ID);
    	if(key < 0)
    		ERR_EXIT("ftok");
    	
    	int shmid = 0;
    	if((shmid = shmget(key,size,flags)) < 0)
    		ERR_EXIT("shmget");
    	
    	return shmid;
    }
    
    int DestroyShm(int shm_id)
    {
    	if(shmctl(shm_id,IPC_RMID,NULL)<0)
    		ERR_EXIT("shmctl");
    	return 0;
    }
    
    int CreatShm(int size)
    {
    	return Creat(size, IPC_CREAT|IPC_EXCL|0666);
    }
    
    int GetShm(int size)
    {
    	return Creat(size, IPC_CREAT);
    }

    server.c 部分

    #include "comm.h"
    
    int main()
    {
    	int shm_id = CreatShm(4096);
    	char* addr = shmat(shm_id,NULL,0);
    	sleep(2);
    	int i = 0;
    	while(i++ < 26)
    	{
    		printf("client said:%s\n",addr);
    		sleep(1);
    	}
    
    	shmdt(addr);
    	sleep(2);
    	DestroyShm(shm_id);
    
    	return 0;
    }
    client.c 部分
    #include "comm.h"
    
    int main()
    {
    	int shm_id = GetShm(4096);
    	sleep(1);
    	char* addr = shmat(shm_id, NULL, 0);
    	int i = 0;
    	printf("hdifhowie\n");
    	while(i < 26)
    	{
    		addr[i] = 'A'+i;
    		i++;
    		addr[i] = 0;
    		sleep(1);
    	}
    
    	shmdt(addr);
    	sleep(2);
    	return 0;
    }

    Makefile文件

    .PHONY:all
    all:server client
    
    server:server.c comm.c
    	gcc -o $@ $^
    client:client.c comm.c
    	gcc -o $@ $^
    
    .PHONY:clean
    clean:
    	rm -f server client
    

    运行结果:


    如果共享内存创建成功,但是后边的执行出现了问题,那么,这块共享内存就需要使用命令手动删除掉了。

    使用命令 ipcs  -m 查看当前共享内存的相关信息

    使用命令 ipcrm  -m  内存块号  删除不需要的共享内存块


    说明:

    共享内存的生命周期是随内核的,不会因为进程提出就释放了,所以,共享内存需要显示的释放。还有就是,共享内存是没有同步互斥机制的,server不会因为共享内存里没有数据而等待。

    展开全文
  • 实验六 进程间通信——共享内存

    千次阅读 2019-09-24 00:17:01
    1、了解采用共享内存通信的原理; 2、掌握共享内存的创建及使用方法。 二、实验内容 1、创建写进程,其功能为创建共享内存并映射到当前进程地址空间,然后向内存写入数据,直至遇到’#’为止; 2、读进程使用和...

    一、实验目的

    1、了解采用共享内存通信的原理;

    2、掌握共享内存的创建及使用方法。

    二、实验内容

    1、创建写进程,其功能为创建共享内存并映射到当前进程地址空间,然后向内存写入数据,直至遇到’#’为止;

    2、读进程使用和写进程相同的KEY创建共享内存并映射到进程地址空间,然后从内存读数据并打印在终端上;

           3、注意通过一定的方式来实现读写进程之间的同步。

    三、源程序

    shm_write.c:

    #include<stdio.h>
    
    #include<stdlib.h>
    
    #include<string.h>
    
    #include<unistd.h>
    
    #include<sys/types.h>
    
    #include<sys/ipc.h>
    
    #include<sys/shm.h>
    
    #include"sem_com.h"
    
    
    
    #define PATHNAME "."
    
    #define PROJ_ID 0x66
    
    
    
    int main() {
    
        // 生成KEY
    
        key_t key = ftok(PATHNAME, PROJ_ID);
    
        if (key < 0) {
    
            perror("生成KEY错误");
    
            exit(-1);
    
        }
    
        // 创建信号量
    
        int semId = semget(key, 1, IPC_CREAT);
    
        if (semId < 0) {
    
            perror("创建信号量失败");
    
            exit(-1);
    
        }
    
        // 初始化信号量
    
        init_sem(semId, 1);
    
        // 创建共享内存
    
        int shmId = shmget(key, 6666, IPC_CREAT);
    
        if (shmId < 0) {
    
            perror("创建共享内存失败");
    
            exit(-1);
    
        }
    
        // 映射共享内存
    
        char *addr = shmat(shmId, NULL, 0);
    
        sleep(1);
    
        int i = 0;
    
        while (1) {
    
            // P操作
    
            sem_p(semId);
    
            printf("write> ");
    
            char c = getchar();
    
            getchar();
    
            addr[i] = c;
    
            i++;
    
            addr[i] = 0;
    
            sleep(1);
    
            // V操作
    
            sem_v(semId);
    
            if (c == '#') {
    
                break;
    
            }
    
        }
    
        //解除共享内存映射
    
        shmdt(addr);
    
        sleep(2);
    
        return 0;
    
    }

    shm_read.c:

    #include<stdio.h>
    
    #include<stdlib.h>
    
    #include<string.h>
    
    #include<unistd.h>
    
    #include<sys/types.h>
    
    #include<sys/ipc.h>
    
    #include<sys/shm.h>
    
    #include"sem_com.h"
    
    
    
    #define PATHNAME "."
    
    #define PROJ_ID 0x66
    
    
    
    // 原型声明
    
    int indexOf(char *str1, char *str2);
    
    
    
    int main() {
    
        // 生成KEY
    
        key_t key = ftok(PATHNAME, PROJ_ID);
    
        if (key < 0) {
    
            perror("生成KEY错误");
    
            exit(-1);
    
        }
    
        // 创建信号量
    
        int semId = semget(key, 1, 0666 | IPC_CREAT | IPC_EXCL);
    
        if (semId < 0) {
    
            perror("创建信号量失败");
    
            exit(-1);
    
        }
    
        // 创建共享内存
    
        int shmId = shmget(key, 6666, 0666 | IPC_CREAT | IPC_EXCL);
    
        if (shmId < 0) {
    
            perror("创建共享内存失败");
    
            exit(-1);
    
        }
    
        // 映射共享内存
    
        char *addr = (char *) shmat(shmId, NULL, 0);
    
        sleep(5);
    
        int index = -1;
    
        while (1) {
    
            // P操作
    
            sem_p(semId);
    
            printf("read> %s\n", addr);
    
            sleep(1);
    
            // V操作
    
            sem_v(semId);
    
            if ((index = indexOf(addr, "#")) != -1) {
    
                break;
    
            }
    
        }
    
        // 解除共享内存映射
    
        shmdt(addr);
    
        sleep(2);
    
        // 删除信号量
    
        del_sem(semId);
    
        // 删除共享内存
    
        if (shmctl(shmId, IPC_RMID, NULL) < 0) {
    
            perror("删除共享内存失败");
    
            exit(-1);
    
        }
    
        return 0;
    
    }
    
    
    
    int indexOf(char *str1, char *str2) {
    
        char *p = str1;
    
        int i = 0;
    
        p = strstr(str1, str2);
    
        if (p == NULL)
    
            return -1;
    
        else {
    
            while (str1 != p) {
    
                str1++;
    
                i++;
    
            }
    
        }
    
        return i;
    
    }

    sem_com.h:

    #include<stdio.h>
    
    #include<stdlib.h>
    
    #include<sys/types.h>
    
    #include<sys/ipc.h>
    
    #include<sys/sem.h>
    
    #include<unistd.h>
    
    
    
    int init_sem(int sem_id, int init_value);
    
    int del_sem(int sem_id);
    
    int sem_p(int sem_id);
    
    int sem_v(int sem_id);
    
    sem_com.c:
    
    #include"sem_com.h"
    
    
    
    union semun
    
    {
    
        int val;
    
        struct semid_ds *buf;
    
        unsigned short *array;
    
    };
    
    
    
    /*信号量初始化*/
    
    int init_sem(int sem_id, int init_value)
    
    {
    
        union semun sem_union;
    
        sem_union.val = init_value;
    
        if (semctl(sem_id, 0, SETVAL, sem_union) < 0)
    
        {
    
            printf("init_sem");
    
            return -1;
    
        }
    
        return 0;
    
    }
    
    
    
    /*从系统中删除信号量*/
    
    int del_sem(int sem_id)
    
    {
    
        union semun sem_union;
    
        if (semctl(sem_id, 0, IPC_RMID, sem_union) < 0)
    
        {
    
            printf("del_sem");
    
            return -1;
    
        }
    
        return 0;
    
    }
    
    
    
    /*P操作*/
    
    int sem_p(int sem_id)
    
    {
    
        struct sembuf sem_b;
    
        sem_b.sem_num = 0;
    
        sem_b.sem_op = -1;
    
        sem_b.sem_flg = SEM_UNDO;
    
        if (semop(sem_id, &sem_b, 1) < 0)
    
        {
    
            printf("sem_p");
    
            return -1;
    
        }
    
        return 0;
    
    }
    
    
    
    /*V操作*/
    
    int sem_v(int sem_id)
    
    {
    
        struct sembuf sem_b;
    
        sem_b.sem_num = 0;
    
        sem_b.sem_op = 1;
    
        sem_b.sem_flg = SEM_UNDO;
    
        if (semop(sem_id, &sem_b, 1) < 0)
    
        {
    
            printf("sem_v");
    
            return -1;
    
        }
    
        return 0;
    
    }

    makefile:

    makelib: sem_com.o
    
        gcc sem_com.c -fPIC -shared -o libsem.so
    
    shm: makelib
    
        cp libsem.so /lib
    
        gcc -o read shm_read.c -L. -lsem
    
        gcc -o write shm_write.c -L. -lsem

    四、实验步骤、结果截图

    (1)使用make工具编译源程序;

    (2)测试运行,先运行read,再运行write。输入字符串,测试程序是否正确。

    运行结果如下:

    运行read的窗口:

    运行write的窗口:

    展开全文
  • 进程间通信共享内存 shared memory ) 1 效率最高 2 存在竞态 七种进程间通信方式: 一 无名管道( pipe ) 二 有名管道( fifo ) 三 共享内存 shared memory 四 信号 sinal 五 消息队列 message queue ) ...
  • Cloudtoid Interprocess是跨平台的共享内存队列,用于进程之间的快速通信( )。 它使用共享的内存映射文件在进程之间进行极其快速和高效的通信,并且在Microsoft内部使用。 :非常快。 跨平台:它支持Windows...
  • 说明:编译时加上参数 -lrt -lpthread 要不然找不到库文件
  • Linux进程间通信共享内存

    千次阅读 2018-05-26 23:45:37
    共享内存通过两个或多个进程共享同一块内存区域来实现进程间通信,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。通常是由一个进程创建一块共享内存区域,然后多个进程可以对其进行访问,一...

    共享内存

      共享内存是Lunix系统中最底层的通信机制,也是最快的通信机制。共享内存通过两个或多个进程共享同一块内存区域来实现进程间的通信,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。通常是由一个进程创建一块共享内存区域,然后多个进程可以对其进行访问,一个进程将要传出的数据存放到共享内存中,另一个或多个进程则直接从共享内存中读取数据。因此这种通信方式是最高效的进程间通信方式。但实际的问题在于,当两个或多个进程使用共享内存进行通信时,同步问题的解决显得尤为重要,否则就会造成因不同进程同时读写一块共享内存中的数据而发生混乱。在通常的情况下,通过使用信号量来实现进程的同步。

    • 共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段)。
    • 如果段的权限设置恰当,每个要访问该段内存的进程都可以把它映射到自己的私有地址空间中。
    • 如果一个进程更新了段中的数据,其他进程也立即会看到更新。
    • 由一个进程创建的段,也可以由另一个进程读写。

    共享内存函数

    1、shmget函数

    功能:⽤来创建共享内存
    原型:int shmget(key_t key, size_t size, int shmflg);
    参数:
      key:这个共享内存段名字
      size:共享内存⼤⼩
      shmflg:由九个权限标志构成,它们的⽤法和创建⽂件时使⽤的mode模式标志是⼀样的
    返回值:成功返回⼀个⾮负整数,即该共享内存段的标识码;失败返回-1
    注意:只有创建权限是0666的才可以用命令行”ipcs -m”查看,其他类型权限的共享内存区无法被这个命令所查看。

    2、shmctl函数

    功能:⽤于控制共享内存
    原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    参数:
      shmid:由shmget返回的共享内存标识码
      cmd:将要采取的动作(有三个可取值)
       IPC_ STAT:把shmid_ ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值
       IPC_ SET:在进程有足够权限的前提下,把共享内存的当前关联值设置为shmid_ds数据结构中给出的值
       IPC_RMID:删除共享内存段
      buf:指向⼀个保存着共享内存的模式状态和访问权限的数据结构
    返回值:成功返回0;失败返回-1

    3、shmat函数

    功能:将共享内存段连接到进程地址空间
    原型:void *shmat(int shmid, const void *shmaddr, int shmflg);
    参数:
      shmid:共享内存标识
      shmaddr:指定连接的地址
      shmflg:它的两个可能取值是SHM_ RND和SHM_RDONLY
    返回值:成功返回⼀个指针,指向共享内存第⼀个节;失败返回-1

    • 说明
      shmaddr若为NULL,核⼼⾃动选择⼀个地址
      shmaddr不为NULL且shmflg⽆SHM_RND标记,则以shmaddr为连接地址
      shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会⾃动向下调整为SHMLBA的整数倍。公式:shmaddr - (shmaddr % SHMLBA)
      shmflg=SHM_RDONLY,表⽰连接操作⽤来只读共享内存

    4、shmdt函数

    功能:将共享内存段与当前进程脱离
    原型:int shmdt(const void *shmaddr);
    参数:
      shmaddr:由shmat所返回的指针
    返回值:成功返回0;失败返回-1
    注意:将共享内存段与当前进程脱离不等于删除共享内存段

    共享内存特点

    1. 可以应用于任何进程
    2. 既能读又能写,双向通信
    3. 可按照随机访问来操作数据
    4. 没有同步和互斥机制
    5. 生命周期随内核

    共享内存实现进程间通信

      以下两个程序是一个进程间通信的例子。这两个程序分别在不同的进程中运行,使用了共享内存进行通信。client读入数据,存放在共享内存中。server则从共享内存中读取数据,显示到屏幕上。

    common.c

    #include "common.h"
    
    #include <stdio.h>
    
    int ShmCommon(int size, int flags){
        key_t key = ftok(PATHNAME, PROJ_ID);
        if(key < 0){
            perror("ftok error");
            return -1;
        }
        int shmid = shmget(key, size, flags);
        if(shmid < 0){
            perror("shmget error");
            return 1;
        }
        return shmid;
    }
    
    int ShmCreate(int size){
        return ShmCommon(size, IPC_CREAT | IPC_EXCL | 0666);
    }
    
    int ShmOpen(){
        return ShmCommon(0, IPC_CREAT);
    }
    
    int ShmDestroy(int shmid){
        int ret = shmctl(shmid, IPC_RMID, NULL);
        if(ret < 0){
            perror("shmctl error");
            return -1;
        }
        return 0;
    }
    
    ////////////////////////////////////////////////////////
    //以下是测试代码
    ///////////////////////////////////////////////////////
    #if 0
    
    void TestCreate(){
        int shmid = ShmCreate(1024);
        printf("shmid = %d\n", shmid);
    }
    
    void TestOpen(){
        int shmid = ShmOpen();
        printf("shmid = %d\n", shmid);
    }
    
    void TestDestroy(){
        int shmid = ShmOpen();
        int ret = ShmDestroy(shmid);
        printf("ret expect 0, actual %d\n", ret);
    }
    
    int main(){
        //TestCreate();
        //TestOpen();
        TestDestroy();
        return 0;
    }
    #endif

    创建之后:
    描述

    销毁之后:
    描述

    client.c

    #include <stdio.h>
    #include <unistd.h>
    #include "common.h"
    
    int main(){
        int shmid = ShmOpen();
        if(shmid < 0){
            perror("ShmOpen failed!");
            return 1;
        }
        sleep(1);
        //把物理内存关联(挂接,attach)到某个进程的虚拟地址空间之中
        char* addr = shmat(shmid, NULL, 0);
        sleep(2);
        int i = 0;
        while(i < 26){
            addr[i] = 'A' + i;
            i++;
            addr[i] = 0;
            sleep(1);
        }
        //将共享内存与当前进程脱离
        shmdt(addr);
        sleep(2);
        return 0;
    }

    server.c

    #include <stdio.h>
    #include <unistd.h>
    #include "common.h"
    
    int main(){
        int shmid = ShmCreate(1024);
        if(shmid < 0){
            perror("ShmCreate failed!");
            return 1;
        }
        char* addr = shmat(shmid, NULL, 0);
        sleep(2);
        int i = 0;
        while(i++ < 26){
            printf("client# %s\n", addr);
            sleep(1);
        }
        shmdt(addr);
        sleep(2);
        ShmDestroy(shmid);
        return 0;
    }

    描述

    详细代码请参考Git

    展开全文
  • Linux_进程间通信_-_共享内存shmget方式
  • 共享内存指 (shared memory)在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器,...共享内存是 Unix下的多进程之间的通信方法 ,这种方法通常用于一个程序的多...
  • 如果一个进程不能影响其他进程或受其他进程影响,那么该进程是独立的,换句话说,不与任何其他进程共享数据的进程是独立的; 如果一个进程能影响其他进程或受其他进程所影响,那么该进程是协作的。换句话说,与其他...
  • 实验原理 Linux下进程通信相关函数除上次实验所用的几个还有 信号量 信号量又称为信号灯它是用来协调不同进程间的数据对象的而最主要的应用是前一节的共享内存方式的进程间通信要调用的第一个函数是semget用以获得一...
  • 进程间通信之——共享内存

    千次阅读 2018-05-05 10:34:57
    共享内存是所有IPC方式中最快的一种,原因在于共享内存一旦映射到进程地址空间,进程间数据的传递就不需要涉及内核。对于管道、FIFO和消息队列,两个进程之间通过这三种方式进行通信,则内核就扮演着“中转站”的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 130,373
精华内容 52,149
关键字:

共享内存进程间通信