共享内存

  • 共享内存区是最快的IPC形式。⼀旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执⾏进入内核的系统调⽤来传递彼此的数据。
  • 先简单介绍一下,也有把共享内存叫做共享存储,共享存储允许两个或者多个进程共享一个给定的存储区。因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种 IPC。使用共享存储时要掌握的诀窍就是,在多个进程之间同步访问一个给定的存储区。若服务器进程正在将数据放入共享存储区,则在他做完这一操作之前,客户进程不应该去取这些数据。
  • 共享存储就是在多个进程将同一个文件映射到它们的地址空间。共享存储和内存映射的文件的不同之处在于,共享存储没有相关的文件。共享存储段是内存的匿名段。

共享内存函数

- shmget 函数
  • 功能:用来创建共享内存
  • 原型 int shmget(key_t key, size_t size, int shmflg);
  • 参数
    • key:这个共享内存段名字,与信号量的semget函数一样,程序需要提供一个参数key(非0整数),它有效地为共享内存段命名,shmget()函数成功时返回一个与key相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1.
    • 不相关的进程可以通过该函数的返回值访问同一共享内存,它代表程序可能要使用的某个资源,程序对所有共享内存的访问都是间接的,程序先通过调用shmget()函数并提供一个键,再由系统生成一个相应的共享内存标识符(shmget()函数的返回值),只有shmget()函数才直接使用信号量键,所有其他的信号量函数使用由semget函数返回的信号量标识符。
    • size:共享内存以字节为单位指定需要共享的内存容量。
      • 这个大小以字节为单位。实现通常将其向上取为系统页长的整数倍,如果应用指定的size值并非系统页长的整数倍,那么最后一页的余下部分是不可使用的。
      • 如果创建一个新段(通常在服务器进程中),则必须指定其size。如果正在引用一个现存的段(一个客户进程),则将size指定为0,。当创建一个新段是,段内的内容初始化为0。
    • shmflg:shmflg是权限标志,由九个权限标志构成,它们的用法和创建文件时使用mode模式标志是一样的。它的作用也与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,可以与IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。
  • 返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回 -1
shmat 函数
  • 功能:将共享内存段连接到进程地址空间
  • 原型 void *shmat(int shmid, const void *shmaddr, int shmflg);
  • 参数
    • shmid : 共享内存标识
    • shmaddr : 指定连接的地址
    • shmflg : 它的两个可能取值是 SHM_RND和SHM_RDONLY
  • 返回值:成功返回⼀个指针,指向共享内存第⼀个字节;失败返回 -1。如果shmat成功执行,那么内核将使与该共享存储段相关的shmid_ds结构中的shm_nattch计数器值加1。
  • 注意:
    • shmaddr 为NULL,则此段连接到由内核选择的一个可用地址上,则是推荐的使用方式。
    • shmaddr不为 NULL 且 shmflg ⽆ SHM_RND 标记,则以shmaddr为连接地址。
    • shmaddr不为NULL且shmflg设置了SHM_RND标记,则连接的地址会⾃动向下调整为SHMLBA的整数倍。
      • 公式:shmaddr - (shmaddr % SHMLBA)
    • 除非只计划在一种硬件上运行应用程序(这在当今是不大可能的),否则不应指定共享内存段所连接到地址。而是应当指定shmaddr为NULL,以便由系统来选择地址。
  • shmflg=SHM_RDONLY,表示连接操作用来只读共享内存,否则以读写方式连接此段。
  • 当对共享内存的操作结束时,则调用shmdt 与该段分离。注意:这不从系统中删除其标识符以及相关的数据结构。该标识符依然存在,直至某个进程(一般是服务器进程)带IPC_RMID命令的调用shmctl 特地删除它为止。
shmdt 函数
  • 功能:将共享内存段与当前进程脱离
  • 原型 int shmdt(const void *shmaddr);
  • 参数
    • shmaddr: 由shmat所返回的指针
  • 返回值:成功返回0;失败返回-1
  • 注意:将共享内存段与当前进程脱离不等于删除共享内存段
shmctl 函数
  • 功能:⽤用于控制共享内存
  • 原型 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • 参数
    • shmid:由shmget返回的共享内存标识码
    • cmd:将要采取的动作(有三个可取值)
      • IPC_STAT:取此段的shmid_ds结构,并将它存储在由buf指向的结构中。
      • IPC_SET:按buf指向的结构体中的值设置与此共享存储段相关的shmid_ds结构中的字段。
      • IPC_RMID:从系统中删除该共享内存
命令 说明
IPC_STAT 把shmid_ds结构中的数据设置为共享内存的当前关联值
IPC_SET 在进程有足够权限的前提下,把共享内存的当前关联值设置为shmid_ds数据结构中给出的值
IPC_RMID 删除共享内存段
  • buf:指向⼀个保存着共享内存的模式状态和访问权限的数据结构
  • 返回值:成功返回0;失败返回-1

来看一个共享内存的代码

  1 #include<unistd.h>2 #include<stdio.h>3 #include<stdlib.h>4 #include<sys/shm.h>5 6 #define IPC_KEY  0x12345677 8 int main()9 {10     int shmid1 = 0;11     shmid1 = shmget(IPC_KEY,32, IPC_CREAT | 0664);12     if(shmid1 < 0)13     {14         perror("shmget error\n");15         return -1;16     }17     void *shm_start = shmat(shmid1,NULL,0);18     if(shm_start == (void*)-1)19     {20         perror("shmat error");21         return -1;22     }23 24     int i = 1;25     while(1)26     {27         sprintf(shm_start,"%s-----%d\n","hello",i++);28         sleep(1);29     }30 31 32     return -1;33 }
  1 #include<unistd.h>2 #include<stdio.h>3 #include<stdlib.h>4 #include<sys/shm.h>5 6 #define IPC_KEY  0x12345677 8 int main()9 {10     int shmid = -1;11     shmid = shmget(IPC_KEY,32, IPC_CREAT|0664);12     if(shmid < 0)13     {14         perror("shmget error\n");15         return -1;16     }17     void *shm_start = shmat(shmid,NULL,0);18     if(shm_start == (void*)-1)19     {20         perror("shmat error");21         return -1;22     }23     while(1)24     {25         printf("不断的问自己:%s",shm_start);26         sleep(1);27     }28 }

在来看一个共享内存的相关代码

comm.h

  1 #ifndef _COMM_H_2 3 #define _COMM_H_4 5 #include <stdio.h>6 #include <sys/types.h>7 #include <sys/ipc.h>8 #include <sys/shm.h>9 #define PATHNAME "."10 #define PROJ_ID 0x666611 #define KEY 0x123456712 13 int createShm(int size);14 int destroyShm(int shmid);15 int getShm(int size);16 17 #endif

comm.c

  1 #include "comm.h"2 static int commShm(int size, int flags)3 {4     key_t _key = ftok(PATHNAME, PROJ_ID);5     if(_key < 0){6         perror("ftok");7         return -1;8     }9     int shmid = 0;10     if( (shmid = shmget(KEY, size, flags)) < 0){11         perror("shmget");12         return -2;13     }14     return shmid;15 }16 int destroyShm(int shmid)17 {18     if(shmctl(shmid, IPC_RMID, NULL) < 0){19         perror("shmctl");20         return -1;21     }   22     return 0;23 }   24 25 int createShm(int size)26 {27     return commShm(size, IPC_CREAT|IPC_EXCL|0666);28 }   29 30 31 int getShm(int size)32 {33     return commShm(size, IPC_CREAT);34 }   

server.c

  1 #include "comm.h"2 3 int main()4 {5     int shmid = createShm(4096);6     char *addr = shmat(shmid, NULL, 0);7     sleep(2);8     int i = 0;9     while(i < 26)10     {11         printf("client# %s\n", addr);12         sleep(1);13         i++;14     }15 16     shmdt(addr);17     sleep(2);18     destroyShm(shmid);19     return 0;20 }
client.c
  1 #include "comm.h"2 #include<string.h>3 4 int main()5 {6     int shmid = getShm(4096);7     if(shmid <= 0)8     {9         perror("creat error!\n");10         return -1;11     }12     sleep(1);13     char *addr = shmat(shmid, NULL,  SHM_RND);14     if(addr == NULL)15     {16         perror("connet error!");17         return -1;18     }19     sleep(2);20     int i = 0;21     while(i<26){22         addr[i] = 'A'+i;23         i++;24         addr[i] = 0;25         sleep(1);26     }27     shmdt(addr);28     sleep(2);29     return 0;30 }

进程间通信------共享内存相关推荐

  1. 操作系统实验报告7:进程间通信—共享内存。实现一个带有n个单元的线性表的并发维护。

    操作系统实验报告7 实验内容 实验内容:进程间通信-共享内存.实现一个带有n个单元的线性表的并发维护. 建立一个足够大的共享内存空间(lock, M),逻辑值lock用来保证同一时间只有一个进程进入M ...

  2. 操作系统实验报告6:进程间通信—共享内存

    操作系统实验报告6 实验内容 实验内容:进程间通信-共享内存. (1).验证:编译运行课件 Lecture 08 例程代码: Linux 系统调用示例 reader-writer 问题:Algorit ...

  3. C# 进程间通信(共享内存)

    原文:C# 进程间通信(共享内存) 进程间通信的方式有很多,常用的方式有: 1.共享内存(内存映射文件,共享内存DLL). 2.命名管道和匿名管道. 3.发送消息 本文是记录共享内存的方式进行进程间通 ...

  4. Linux基础入门--进程间通信--共享内存

    Linux基础入门--进程间通信--共享内存 1.共享内存IPC原理 2.共享内存管理 1.共享内存IPC原理 共享内存进程间通信机制主要用于实现进程间大量的数据传输,共享内存是在内存单独开辟的一段内 ...

  5. Linux下进程间通信--共享内存:最快的进程间通信方式

    内存共享最新整理: Linux下进程间通信-共享内存 - 码到城攻共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式https://www.codecomeon.com/posts/109/ ...

  6. 【Linux】Linux进程间通信——共享内存/消息队列/守护进程

    文章目录 进程间通信--共享内存/守护进程 一, 共享内存 1. 共享内存概念 2. 共享内存使用 1. 共享内存使用步骤 2. 共享内存操作函数 3. 共享内存常用操作命令 4. 共享内存使用示例: ...

  7. 【Linux系统编程】进程间通信--共享内存

    概述 共享内存是进程间通信中最简单的方式之一.共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针.当一个进程改变了这块地址中的内容的时 ...

  8. Linux系统【五】进程间通信-共享内存mmap

    mmap函数 #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags,int fd, ...

  9. c++ fork 进程时 共享内存_c/c++ Linux 进程间通信------共享内存

    1. 什么是共享内存 共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是 ...

  10. 【Linux】进程间通信-共享内存

    前言 我们知道,在Linux中,进程是相互独立存在的,不存在直接让进程之间互相通信的方式.但是如果我们能让不同进程之间见到同一块内存,也就是都能读写这片区域是不是就能够达到进程间通信呢? 事实证明确实 ...

最新文章

  1. JavaScript调用Applet的函数
  2. Java:由浅入深揭开 AOP 实现原理
  3. Round-Robin负载均衡算法及其实现原理
  4. 别给小偷可乘之机!日本山形县警方呼吁民众“锁门”
  5. Andorid之Log图文详解(Log.v,Log.d,Log.i,Log.w,Log.e)的用法总结
  6. elasticsearch中的优先级线程池
  7. 质性研究工具_MAXQDA在质性数据分析中的使用——免费的中文在线研讨会!
  8. 机器视觉:嵌入式视觉系统中的接口
  9. SEO专题之四:如何合理有效选定关键字
  10. 云计算开发一般负责什么工作呢?云计算是做什么的?
  11. 高乐计算机课程,长春理工大学
  12. (转)CGJ02、BD09、西安80、北京54、CGCS2000常用坐标系详解
  13. DSPE-PEG-Alkyne/CHO 磷脂聚乙二醇炔基/醛基
  14. 游戏《迷你世界》如何吸引小鸡到鸡窝里?这些道具很重要!
  15. IOS电影播放器—MPMoviePlayerController
  16. UVA - 10118 Free Candies 记忆化搜索
  17. 20171693测绘工程三班钱慧亚 结构体笔记
  18. “少走四十年弯路”,年轻人已经考虑养老了?
  19. 蚂蚁笔记(Leanote)------一款国内优秀的开源项目
  20. linux运维之道 2.3 账户与安全

热门文章

  1. gnuradio上怎么使用python文件_使用Python下载文件的简单示例
  2. 声音模仿_澳洲这种鸟堪称“超级声音模仿秀”,比八哥还牛,却正遭山火毁灭...
  3. Matlab运算之 norm,cross,makehgtform,asin(acos)
  4. 论文阅读笔记(七)——Thin MobileNet
  5. ValueError: Cannot feed value of shape (784,) for Tensor 'Placeholder:0', which has shape '(?, 784)'
  6. 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
  7. 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字(简单易懂)
  8. Elasticsearch Index Template(索引模板)
  9. 性能优化-内存泄露常见例子
  10. centos 安装jenkins