1. 共享内存:

共享内存方式可以在多个进程直接共享数据,因为其直接使用内存,不要多余的拷贝,是速度最快的IPC方式;

共享内存有两种实现方式,使用mmap和shm方式,如下图:

(1) mmap方式是将文件与进程地址空间进行映射,对实际物理内存影响小;

(2) shm方式是将每个进程的共享内存与实际物理存储器进行映射,对实际物理内存影响大;

由于XSI IPC自身缺点,所以建议使用mmap来实现共享内存;

2. mmap相关函数原型:

  1. #include <sys/mman.h>
  2.  
  3. void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);
  4.  
  5. ret = 成功返回映射区域开始地址,失败返回MAP_FAILED

addr-参数用来指定映射区域的起始地址。通常设置为0,表示有系统选择映射区域的起始位置;

filedes-要映射文件的描述符。在映射文件到地址空间之前,先要打开文件;

len-映射的字节数;

off-要映射字节在文件中的起始偏移量;

prot-对映射存储区的保护要求,指定为PROT_NONE(不可访问), PROT_READ(可读), PROT_WRITE(可写), PROT_EXEC(可执行)的任意组合或者按位或;

但是对于映射存储区的保护要求不能超过文件open的权限,比如文件是只读打开的,则不能指定PROT_WRITE;

flag-MAP_FIXED 返回值必须等于addr,如果未制定此标志,addr非0,则作为一种建议,内核不保证会使用该地址。为了获得最大的可移植性,建议addr指定为0;

MAP_SHARED 说明了本进程对映射区域进行储存操作的配置。此标志指定存储操作修改映射文件,也就是相当于对该文件执行write;

MAP_PRIVATE 本标志说明对映射区存储操作会创建该映射的一个副本。所以后续操作都会引用该副本,而不是原始文件;

MAP_SAHRED 和 MAP_PRIVATE 必须指定其一,但是不能同时指定;

修改现有映射区的权限,与上面mmap中的prot字段相同;

  1. #include <sys/mman.h>
  2.  
  3. int mprotect(void *addr, size_t len, int prot);
  4.  
  5. ret = 成功返回0,失败返回-

如果共享内存中的页已被修改,则可以调用msync将该页冲洗到映射的文件中;

如果映射是私有的,那么不修改映射文件;

  1. #include <sys/mman.h>
  2.  
  3. int msync(void *addr, size_t len, int flags);
  4.  
  5. ret = 成功返回0 失败返回-

flags- MS_ASYNC和MS_SYNC必选其一;

   MS_ASYNC-异步sync,无需等待,系统调度;

MS_SYNC-同步sync,需要等到操作完成;

MS_INVALIDATE-可选标志,通知操作系统丢弃没有同步的页;--一般不使用;

进程终止,或者调用munmap,内存映射就被自动解除,关闭文件描述符filedes并不会解除映射;

调用munmap不会是映射内存内容写到磁盘文件,share类型写磁盘是内核根据算法自动执行,private则丢弃修改;

  1. #include <sys/mman.h>
  2.  
  3. int munmap(caddr_t addr, size_t len);
  4.  
  5. ret-成功返回0 失败返回-

3.  文件映射到进程位置:

文件映射到进程地址空间中堆和栈直接的一段内存。

4. 子进程影响:

fork之后,因为子进程复制父进程的地址空间,而存储映射是该地址空间的一部分,所以子进程继承了该存储映射区域,但是当调用了exec函数组之后的新程序则不继承该映射区;

测试代码:--测试两个进程通过mmap映射信息,测试共享时,数据情况,和共享后数据情况;

common.h

  1. #include <sys/mman.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <fcntl.h>
  5. #include <string.h>
  6.  
  7. #define MMAP_FILE "/var/tmp/test_mmap"
  8. #define NAME_LEN 64
  9.  
  10. typedef struct book {
  11. int id;
  12. char name[NAME_LEN];
  13. }book_t;

mmap_proc1.c -- 进程1,做映射,映射超过文件长度的区域

  1. #include "common.h"
  2.  
  3. int main(int argc, char *argv[])
  4. {
  5. int fd = -;
  6. int i = ;
  7. book_t *book = NULL;
  8.  
  9. if ((fd = open(MMAP_FILE, O_RDWR | O_CREAT | O_TRUNC)) < ){
  10. perror("open file error\n");
  11. return -;
  12. }
  13.  
  14. if (lseek(fd, sizeof(book_t) * - , SEEK_SET) < ){
  15. perror("lseek error\n");
  16. close(fd);
  17. return -;
  18. }
  19.  
  20. write(fd, "", );
  21.  
  22. if ((book = (book_t *)mmap(NULL, sizeof(book_t) * , PROT_READ|PROT_WRITE, MAP_SHARED, fd, )) == MAP_FAILED){
  23. perror("mmap error\n");
  24. return -;
  25. }
  26.  
  27. close(fd);
  28.  
  29. for (i = ; i < ; i++){
  30. char name[] = { };
  31. snprintf (name, , "book-%d", i);
  32.  
  33. (*(book + i)).id = i;
  34. strncpy((*(book + i)).name, name, NAME_LEN - );
  35. }
  36.  
  37. sleep();
  38.  
  39. munmap(book, sizeof(book_t) * );
  40.  
  41. return ;
  42. }

mmap_proc2.c -- 进程2,做映射,映射与进程1相同区域

  1. #include "common.h"
  2.  
  3. int main(int argc, char *argv[])
  4. {
  5. int fd = -;
  6. int i = ;
  7. book_t *book = NULL;
  8.  
  9. if ((fd = open(MMAP_FILE, O_RDWR | O_CREAT)) < ){
  10. perror("open file error\n");
  11. return -;
  12. }
  13.  
  14. if ((book = (book_t *)mmap(NULL, sizeof(book_t) * , PROT_READ|PROT_WRITE, MAP_SHARED, fd, )) == MAP_FAILED){
  15. perror("mmap error\n");
  16. return -;
  17. }
  18.  
  19. close(fd);
  20.  
  21. for (i = ; i < ; i++){
  22. printf("id:%d, name:%s\n", (*(book+i)).id, (*(book+i)).name);
  23. }
  24.  
  25. munmap(book, sizeof(book_t) * );
  26.  
  27. return ;
  28. }

Linux-进程间通信(三): 共享内存的更多相关文章

  1. Linux进程间通信—使用共享内存

    Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内 ...

  2. Linux进程间通信——使用共享内存

    一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存. ...

  3. Linux进程间通信——使用共享内存(转)

    一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存. ...

  4. linux进程间通信之共享内存篇

    本文是对http://www.cnblogs.com/andtt/articles/2136279.html中共享内存(上)的进一步阐释说说明 1 共享内存的实现原理 共享内存是linux进程间通讯的 ...

  5. Linux进程间通信(四) - 共享内存

    共享内存的优势 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只 ...

  6. linux进程间通信之共享内存学习记录

    进程 狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed). 广义定义:进程是一个具有一定独立功能的 ...

  7. Linux进程间通信之共享内存

    一,共享内存  内核管理一片物理内存,允许不同的进程同时映射,多个进程可以映射同一块内存,被多个进程同时映射的物理内存,即共享内存.  映射物理内存叫挂接,用完以后解除映射叫脱接. 1,共享内存的特点 ...

  8. linux进程间通信同步-共享内存

    参考:https://www.cnblogs.com/charlesblc/p/6142868.html 使用有名信号量,sem_open().sem_close().sem_post().sem_w ...

  9. Linux环境进程间通信(五): 共享内存(上)

    linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...

  10. 浅析Linux下进程间通信:共享内存

    浅析Linux下进程间通信:共享内存 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以它是最快的一种IPC.使用共享内存要注意的是,多个进程之间对一给定 ...

随机推荐

  1. [剑指Offer] 47.求1+2+3+...+n

    题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). [思路]用&&的短路思想来求和 ...

  2. SpringBoot2.0(三) 文件上传

    SpringBoot中发起文件上传示例: /** * 文件上传 * @param multipartFile * @param path * @return */ @RequestMapping(va ...

  3. 【Python】python更新数据库脚本两种方法

    最近项目的两次版本迭代中,根据业务需求的变化,需要对数据库进行更新,两次分别使用了不同的方式进行更新. 第一种:使用python的MySQLdb模块利用原生的sql语句进行更新   1 import ...

  4. RT-thread内核之定时器管理

    一.前言 rt-thread采用软件定时器线程模式或硬件定时器中断模式来实现系统定时器管理.而rt-thread操作系统在默认情况下是采用的硬件定时器中断模式的方式,用户可以通过宏定义RT_USING ...

  5. poj2018——Best Cow Fences

    Description Farmer John's farm consists of a long row of N (1 <= N <= 100,000)fields. Each fie ...

  6. 自学Python快速入门

    1 helloworld#基本语法print("hello") #换行print('1221312\12312312\2312312321312\21312312') ##表示注释 ...

  7. SPOJ1825/FTOUR2:Free tour II——包看得懂/看不懂题解

    http://www.spoj.com/problems/FTOUR2/en/ 题目大意:给一棵黑白染色的树,求边权和最大且经过黑点不超过K的路径. ———————————————————— 前排膜拜 ...

  8. 搞笑的代码 ( funny )

    搞笑的代码 ( funny ) 在OI界存在着一位传奇选手——QQ,他总是以风格迥异的搞笑代码受世人围观 某次某道题目的输入是一个排列,他使用了以下伪代码来生成数据 while 序列长度<n d ...

  9. js正则:两边字符固定,中间任意字符

    求些一个js正则!两边字符固定,中间任意字符.在一个长字符串里面匹配一小段,这一小段字符串开头和结尾都是固定的字符,就是中间是任意长度的字符.怎么写? /aa.+aa/ aa是你的固定字符,如果是反斜 ...

  10. phantomjs 无法打开https网站

    最近一直在用phantomjs 自动登陆并爬取一些数据,突然发现爬取https类型的网站的时候无法正常操作了 困扰了两天的问题在经过google和stackoverflow的一番搜索后发现原来Phan ...