linux进程通信--共享内存

原创 2016年06月01日 14:35:15

特点

共享内存是linux进程进行通信的一种高效的传递方式,linux内核在内存中留下一块存储区,进程通过将共享内存的地址映射到进程空间,就可以实现直接对数据进行操作,但是共享内存自身没有同步机制,因此需要适用其他的方式实现对共享内存空间的读写进行同步。通信结构简图如图1所示。

                        图1 多进程共享内存通信原理示意图

实现过程与操作函数

共享内存的操作分为以下几个步骤:

  • 创建共享内存
  • 映射共享内存
  • 删除共享内存
  • 释放共享内存
    /************************************

    int shmget(key_t key, size_t size, int shmflg);
    //创建共享内存
    //size 共享内存的大小,
    shmflag类似于前面的消息队列和信号量的创建,
    采用一般采用0666|IPC_CREAT,实现不存在内存空间的时候实现创建,存
    在的时候实现获取共享内存,返回创建的内存的标志符


----------

    void *shmat(int shmid, const void *shmaddr, int shmflg);
    //映射共享内存
     shmid为创建时的标志符;
    shmaddr:将共享内存映射到指定位置(若为 0 则表示把该段共享内存
            映射到调用进程的地址空间)
    shmflg:
            SHM_RDONLY:共享内存只读
            默认 0:共享内存可读写

----------

    int shmdt(const void *shmaddr);
        //释放共享内存Shmaddr:被映射的共享内存段地址,


----------

    int shmctl(int shmid, int cmd, struct shmid_ds *buf);
        // 删除共享内存   
    shmid
        共享内存标识符
    cmd
        IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
        IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的
                uid、gid、mode复制到共享内存的shmid_ds结构内
        IPC_RMID:删除这片共享内存
    buf 
        共享内存管理结构体。

    /*************************************************/

应用实例

实现两个进程通过共享内存交换数据,发送端接收终端数据,发送至共享内存,读取端从共享内存读取数据,实现数据的交换。由于共享内存自身无法实现进程同步,因此定义了write_flag标志位,作为读写的标志实现

读取端例程

#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>
#include "shmheader.h"
#include <string.h>`
int main()
{
int shm_id;
int run_flag=1;
void *shm_mem=NULL;
struct shared_mem *shared;//用来存放地址
shm_id=shmget((key_t)1234,sizeof(struct shared_mem),0666|IPC_CREAT);// 创建共享内存
if(shm_id==-1)
{
    printf("Creat shared_mem failed\n");
    exit(EXIT_FAILURE);
}
// 将共享内存链接到当前进程
shm_mem=shmat(shm_id,(void *)0,0);
if(shm_mem==(void *)-1)
{
    printf("connect memeory failed\n");
    exit(EXIT_FAILURE);
}
//打印地址
shared=(struct shared_mem *)shm_mem;
shared->write_flag=0;
while(run_flag)
{
    if(shared->write_flag==1)//   等待写结束
    {
        printf("You Write is:%s",shared->text);
        sleep(1);
        shared->write_flag=0;
        if(strncmp(shared->text,"end",3)==0)
        {
            run_flag=0;
        }
    }
}
if(shmdt(shm_mem)==-1)
{
    printf("disconnect memeory failed!\n");
    exit(EXIT_FAILURE);
}
//读取结束要删除共享内存
if(shmctl(shm_id,IPC_RMID,0)==-1)
{
    printf("delete memeory failed!\n");
    exit(EXIT_FAILURE);

}
sleep(2);
return 0;
}`

发送端例程

#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/types.h>

#include <string.h>

#include "shmheader.h"

#define BUF_SIZE 512

int main()
{
    int shm_id;
    int run_flag=1;
    void *shm_mem=NULL;
    struct shared_mem *shared;//用来存放地址
    char buffer[BUF_SIZE+1];
    shm_id=shmget((key_t)1234,sizeof(struct shared_mem),0666|IPC_CREAT);// 创建共享内存
    if(shm_id==-1)
    {
        printf("Creat shared_mem failed\n");
        exit(EXIT_FAILURE);
    }
    // 将共享内存链接到当前进程
    shm_mem=shmat(shm_id,(void *)0,0);
    if(shm_mem==(void *)-1)
    {
        printf("connect memeory failed\n");
        exit(EXIT_FAILURE);
    }
    //打印地址
//  printf("share mameory adress is %X\n",(int)shm_mem);
    shared=(struct shared_mem*)shm_mem;
    //shared.write_flag=1;  //关闭写
    while(run_flag)
    {
        //一直检测写
        while(shared->write_flag)   //如果 一直不可写再次等待
        {
            sleep(1);
            printf("please waiting ....\n");
        }
        printf("please write :");
        fgets(buffer,BUF_SIZE,stdin);
        strncpy(shared->text,buffer,BUF_SIZE);

        shared->write_flag=1;
        if(strncmp(buffer,"end",3)==0)
        {
            run_flag=0;
        }
    }
    if(shmdt(shm_mem)==-1)
    {
        printf("disconnect memeory failed!\n");
        exit(EXIT_FAILURE);
    }
    sleep(2);

    return 0;
}

头文件

#ifndef _SHMHEADER_H
#define _SHMHEADER_H

#define TEXT_SIZE 2048
struct shared_mem
{

    int write_flag;//定义的读写标志位
    char text[TEXT_SIZE];
};

#endif

总结

使用共享内存实现进程通信,接口简单、通信方便、效率高;但是缺乏同步机制,需要借用其他的方法实现同步。

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

linux系统中的进程通信(消息队列、共享内存、信号量)

消息队列:类似与管道只能单项通信,消息队列由消息组成,消息可以有不同的数据结构,也可以由有优先级,能够更加灵活的通 信。消息队列使用int msgget(key_t key,int flags)获得或...

linux进程通信(一)--共享内存+信号量

原文地址:http://fengtong.iteye.com/blog/456661 /*server.c:向共享内存中写入People*/ #include #include #include...
  • zx824
  • zx824
  • 2012-08-30 17:47
  • 1053

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

linux进程通信(一)--共享内存--mmap()

二、mmap()及其相关系统调用 mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read...

撸代码--linux进程通信(基于共享内存)

1.实现有亲缘关系(父子)的进程通信,完成父写子读的操作。 思路分析:1)首先我们需要创建一个共享内存。       2)父子进程的创建要用到fork函数。fork函数创建后,两...

Linux\Unix IPC进程通信实例分析(一):共享内存通信---系统V

前些天看到有个博主写博客采用问答式的叙述方法:把很多知识点通过一问一答的形式把文章串起来,我觉得这种形式不错,便于突出重点。后面我也做下尝试,一边写写博客,一边回顾一下自己对IPC进程通信的认识。 ...

Linux\Unix IPC进程通信实例分析(一):共享内存通信---文件映射mmap方式

说明:这个例子是采用共享文件映射形式,写端写入数据,读端读取数据。 写端:  /*-------------map_normalfile1.c-----------*/ #include #in...

进程通信之共享内存与信号量

信号量:通过设置一个值val大于0的整数,表示当前最多允许val个进程进入临界区。同时定义P函数,函数中对val进行减1操作,每当一个进程进入临界区时执行一次P函数,当val为0时当前进程等待。定义V...

进程通信-共享内存-mmap()-code1

参考了sjmw888的用例,在其基础上做了修改,用于三个进程共享内存, 但每个进程只对特定区段改写. 简单模拟,未使用信号、信号量等来控制。 /*-------------map_normalfi...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)