进程间的通信——共享内存

原创 2018年04月15日 21:12:11

进程间的通信——消息队列https://blog.csdn.net/q496958148/article/details/79951727
进程间的通信——信号量https://blog.csdn.net/q496958148/article/details/79977093
进程间的通信——管 道https://blog.csdn.net/q496958148/article/etails/79948367

概述:

共享内存是最快的IPC形式。因为只要建立这样一个环境的话,进程间的通信就需要内核的传递了,只要俩进程看到同一块地址空间,只要任何一个做出修改,其他的都可以看到。而相对应的管道、消息队列都是你写进去然后内核进行解析成二进制。然后转移到接收端,又得将二进制解析成正常的信息。这样就会大大降低效率。

共享内存示意图:
这里写图片描述

共享内存的数据结构:

 struct shmid_ds {
                struct ipc_perm shm_perm;        /* operation perms */
                int     shm_segsz;               /* size of segment (bytes) */
                time_t  shm_atime;               /* last attach time */
                time_t  shm_dtime;               /* last detach time */
                time_t  shm_ctime;               /* last change time */
                unsigned short  shm_cpid;        /* pid of creator */
                unsigned short  shm_lpid;        /* pid of last operator */
                short   shm_nattch;              /* no. of current attaches */

                                                 /* the following are private */

                unsigned short   shm_npages;     /* size of segment (pages) */
                unsigned long   *shm_pages;      /* array of ptrs to frames -> SHMMAX */ 
                struct vm_area_struct *attaches; /* descriptors for attaches */
        };
  • 创建共享内存
       int shmget(key_t key, size_t size, int shmflg);
       //key 这个内存段的名字(暗号和消息队列一样)
       //size 共享内存的大小
       //shmflg IPC_CREAT:创建新的共享内存。 IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消共享内存已经存在,则返回错误。 IPC_NOWAIT:读写共享内存要求无法满足时,不阻塞。
  • 将共享内存连接到进程的地址空间(上面的那个图)
       void *shmat(int shmid, const void *shmaddr, int shmflg);
    //shmid 共享内存标识
    //shmaddr 指定连接的地址
    //shmflg SHM_RND 和 SHM_RDONLY 俩个取值
    //返回值成功为指向共享内存的指针,失败为-1
  • 将共享内存与当前进程脱离
        int shmdt(const void *shmaddr);
    //shmaddr 由shmat返回的指向共享内存的地址
    //返回值成功为0,失败为-1
    //切记 只是将共享内存和进程的连接脱离,并不是将共享内存删除(只是取消了它们之间的映射关系)
  • 控制共享内存
        int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    //shmid 共享内存标示符
    //cmd 将要采取的动作IPC_STAT将传进来的参数设置为共享内存的关联值 IPC_SET在有权限的前提下,将共享内存的关联值跟换为传进来参数的值 IPC_RMID删除共享内存
    //buf 指向一个保存着共享内存的模式状态和访问权限的数据结构
    //返回值成功为0,失败为-1 

实例:
要求功能:进程A每隔一秒往共享内存写一个数据,进程B也是每隔一秒打印出当前共享内存的数据,并且要求在30秒之内自动退出,删除共享内存。

shm.h:

#pragma once

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

#define TAPH "."
#define NUM 0x6666

int createShm(int size);

int getShm(int size);

int destroyShm(int shmid);

shm.c:

#include "shm.h"

int createShm(int size)
{
    key_t key = ftok(TAPH,NUM);
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }

    int shmid = shmget(key,size,IPC_CREAT|IPC_EXCL|0666);
    if(shmid < 0)
    {
        perror("shmget");
        return -1;
    }
    return shmid;
}

int getShm(int size)
{
    key_t key = ftok(TAPH,NUM);
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }

    int shmid = shmget(key,size,IPC_CREAT);
    if(shmid < 0)
    {
        perror("shmget");
        return -1;
    }
    return shmid;
}

int destroyShm(int shmid)
{
    int i = shmctl(shmid,IPC_RMID,NULL);
    if(i < 0)
    {
        perror("shmctl");
        return -1;
    }
    return 0;
}

server.c:

#include "shm.h"

int main()
{
    int shmid = createShm(1024);

    void *pshm = shmat(shmid,NULL,0);
    int i = 0;
    while(i < 30)
    {
        printf("--:%s\n",pshm);
        i++;
        sleep(1);
    }
    shmdt(pshm);
    destroyShm(shmid);
    return 0;
}

client.c:

#include "shm.h"

int main()
{
    int shmid = getShm(1024);
    sleep(1);
    char *pshm = shmat(shmid,NULL,0);
    int i = 0;
    int j = 0;
    while(i < 30)
    {
        pshm[i] = 'a' + i;
        i++;
        pshm[i] = 0;
        if(i >14)
        {
            pshm[i-2*j] = '\0';
            j++;
        }
        sleep(1);
    }
    shmdt(pshm);
    sleep(1);
    return 0;
}

Makefile:

.PHONY:all
all:client server


client:client.c shm.c
    gcc $^ -o $@;
server:server.c shm.c
    gcc $^ -o $@;

.PHONY:clean
clean:
    rm -f client server

效果图:
这里写图片描述

共享内存中如果出现一下情况:
这里写图片描述
这里写图片描述

进程间通信之共享内存初步

基本概念共享内存   共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。  ...
  • lzjsqn
  • lzjsqn
  • 2016-12-24 22:32:15
  • 773

进程间通信方式——共享内存

在程序的运行中,我们必定会有关于进程与进程间通信的问题。而我们的先辈早已为我们准备了关于解决这些问题的方法。这些方法主要有几种:无名管道,有名管道,信号,消息队列,共享内存以及信号灯(信号量)等几种方...
  • farsight2009
  • farsight2009
  • 2016-10-28 11:29:39
  • 1319

进程之间的通讯之共享内存

刚刚我们了解了我们的IPC对象,我们知道我们的System V进程间的通信,在系统建立IPC通信的时候,必须指定一个ID值。而该ID的值,我们就可以通过ftok()函数来间接的得到。共享内存就是我们的...
  • farsight2009
  • farsight2009
  • 2016-09-21 15:14:56
  • 470

uc笔记09---进程通信,管道,进程间通信,共享内存,消息队列,信号量,IPC 命令

1.    基本概念     何为进程间通信:     进程间通信 (Interprocess Communication, IPC) 是指两个,     或多个进程之间进行数据交换的过程。   ...
  • wolfsun3
  • wolfsun3
  • 2015-09-30 17:04:05
  • 536

进程间通信:共享内存(代码实现)

共享内存:1.共享内存就是允许两个不相关的进程访问同一个逻辑内存;                     2.共享内存是在两个正在运行的进程之间共享和传递数据的一种最有效的方式;        ...
  • wangiijing
  • wangiijing
  • 2016-07-06 18:17:36
  • 4383

Linux进程间通信 共享内存+信号量+简单例子

每一个进程都有着自己独立的地址空间,比如程序之前申请了一块内存,当调用fork函数之后,父进程和子进程所使用的是不同的内存。因此进程间的通信,不像线程间通信那么简单。但是共享内存编程接口可以让一个进程...
  • u011408355
  • u011408355
  • 2015-08-19 16:42:06
  • 2629

Linux进程间通信之共享内存(一)

Linux共享内存(一) Linux系统编程我一直看 ,只是讲的太简单了,通常是书和网络上的资料结合着来掌握才比较全面 .在掌握了书上的内容后,再来都其他资料 . 原文链接 http://www....
  • zhouwei1221q
  • zhouwei1221q
  • 2015-08-31 13:25:11
  • 884

Windows进程间通信之共享内存

  • 2013年05月13日 21:02
  • 187KB
  • 下载

【进程间通信】共享文件映射

FileMap.h#include "..\include\error_type.h" #include #include #include using namespace std; cla...
  • u014161864
  • u014161864
  • 2014-05-09 19:29:27
  • 949

共享内存,管道,socket等进程间通信方式的优缺点

进程间通信的方式有很多,常见的有信号,信号量,消息队列,管道,共享内存,和socket等,这里我们主要讨论管道,共享内存,和socket,其他的比较简单只做简单的介绍。 信号:信号主要用于通知某个进程...
  • D_Guco
  • D_Guco
  • 2016-12-08 21:14:01
  • 7769
收藏助手
不良信息举报
您举报文章:进程间的通信——共享内存
举报原因:
原因补充:

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