Linux-进程间通信(三): 共享内存
1. 共享内存:
共享内存方式可以在多个进程直接共享数据,因为其直接使用内存,不要多余的拷贝,是速度最快的IPC方式;
共享内存有两种实现方式,使用mmap和shm方式,如下图:
(1) mmap方式是将文件与进程地址空间进行映射,对实际物理内存影响小;
(2) shm方式是将每个进程的共享内存与实际物理存储器进行映射,对实际物理内存影响大;
由于XSI IPC自身缺点,所以建议使用mmap来实现共享内存;
2. mmap相关函数原型:
#include <sys/mman.h> void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off); 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字段相同;
#include <sys/mman.h> int mprotect(void *addr, size_t len, int prot); ret = 成功返回0,失败返回-
如果共享内存中的页已被修改,则可以调用msync将该页冲洗到映射的文件中;
如果映射是私有的,那么不修改映射文件;
#include <sys/mman.h> int msync(void *addr, size_t len, int flags); ret = 成功返回0 失败返回-
flags- MS_ASYNC和MS_SYNC必选其一;
MS_ASYNC-异步sync,无需等待,系统调度;
MS_SYNC-同步sync,需要等到操作完成;
MS_INVALIDATE-可选标志,通知操作系统丢弃没有同步的页;--一般不使用;
进程终止,或者调用munmap,内存映射就被自动解除,关闭文件描述符filedes并不会解除映射;
调用munmap不会是映射内存内容写到磁盘文件,share类型写磁盘是内核根据算法自动执行,private则丢弃修改;
#include <sys/mman.h> int munmap(caddr_t addr, size_t len); ret-成功返回0 失败返回-
3. 文件映射到进程位置:
文件映射到进程地址空间中堆和栈直接的一段内存。
4. 子进程影响:
fork之后,因为子进程复制父进程的地址空间,而存储映射是该地址空间的一部分,所以子进程继承了该存储映射区域,但是当调用了exec函数组之后的新程序则不继承该映射区;
测试代码:--测试两个进程通过mmap映射信息,测试共享时,数据情况,和共享后数据情况;
common.h
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h> #define MMAP_FILE "/var/tmp/test_mmap"
#define NAME_LEN 64 typedef struct book {
int id;
char name[NAME_LEN];
}book_t;
mmap_proc1.c -- 进程1,做映射,映射超过文件长度的区域
#include "common.h" int main(int argc, char *argv[])
{
int fd = -;
int i = ;
book_t *book = NULL; if ((fd = open(MMAP_FILE, O_RDWR | O_CREAT | O_TRUNC)) < ){
perror("open file error\n");
return -;
} if (lseek(fd, sizeof(book_t) * - , SEEK_SET) < ){
perror("lseek error\n");
close(fd);
return -;
} write(fd, "", ); if ((book = (book_t *)mmap(NULL, sizeof(book_t) * , PROT_READ|PROT_WRITE, MAP_SHARED, fd, )) == MAP_FAILED){
perror("mmap error\n");
return -;
} close(fd); for (i = ; i < ; i++){
char name[] = { };
snprintf (name, , "book-%d", i); (*(book + i)).id = i;
strncpy((*(book + i)).name, name, NAME_LEN - );
} sleep(); munmap(book, sizeof(book_t) * ); return ;
}
mmap_proc2.c -- 进程2,做映射,映射与进程1相同区域
#include "common.h" int main(int argc, char *argv[])
{
int fd = -;
int i = ;
book_t *book = NULL; if ((fd = open(MMAP_FILE, O_RDWR | O_CREAT)) < ){
perror("open file error\n");
return -;
} if ((book = (book_t *)mmap(NULL, sizeof(book_t) * , PROT_READ|PROT_WRITE, MAP_SHARED, fd, )) == MAP_FAILED){
perror("mmap error\n");
return -;
} close(fd); for (i = ; i < ; i++){
printf("id:%d, name:%s\n", (*(book+i)).id, (*(book+i)).name);
} munmap(book, sizeof(book_t) * ); return ;
}
Linux-进程间通信(三): 共享内存的更多相关文章
- Linux进程间通信—使用共享内存
Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内 ...
- Linux进程间通信——使用共享内存
一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存. ...
- Linux进程间通信——使用共享内存(转)
一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存. ...
- linux进程间通信之共享内存篇
本文是对http://www.cnblogs.com/andtt/articles/2136279.html中共享内存(上)的进一步阐释说说明 1 共享内存的实现原理 共享内存是linux进程间通讯的 ...
- Linux进程间通信(四) - 共享内存
共享内存的优势 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只 ...
- linux进程间通信之共享内存学习记录
进程 狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed). 广义定义:进程是一个具有一定独立功能的 ...
- Linux进程间通信之共享内存
一,共享内存 内核管理一片物理内存,允许不同的进程同时映射,多个进程可以映射同一块内存,被多个进程同时映射的物理内存,即共享内存. 映射物理内存叫挂接,用完以后解除映射叫脱接. 1,共享内存的特点 ...
- linux进程间通信同步-共享内存
参考:https://www.cnblogs.com/charlesblc/p/6142868.html 使用有名信号量,sem_open().sem_close().sem_post().sem_w ...
- Linux环境进程间通信(五): 共享内存(上)
linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...
- 浅析Linux下进程间通信:共享内存
浅析Linux下进程间通信:共享内存 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以它是最快的一种IPC.使用共享内存要注意的是,多个进程之间对一给定 ...
随机推荐
- C语言中printf直接打出2进制数是%什么?16进制是什么?
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h&g ...
- [OS] 生产者-消费者问题(有限缓冲问题)
·最简单的情形--(一个生产者 + 一个消费者 + 一个大小为1的有限缓冲) 首先来分析其中的同步关系: ·必须在生产者放入一个产品之后,消费者才能够从缓冲中取出产品来消费.·只有在消费者从缓冲区中取 ...
- sql语句中的insert 和 insert into 的区别?into有什么用?
insert into tableName values(........) insert tableName (字段名1,字段名2,...)values(......)看语句结构就知道区别了 .in ...
- Bootstrap 栅格系统初识
以下理论内容copy自bootstrap中文网(一个不错的bootstrap学习网站). 栅格系统 Bootstrap 提供了一套响应式.移动设备优先的流式栅格系统,随着屏幕或视口(viewport) ...
- BZOJ 1037 生日聚会(神DP)
这题的DP很难想,定义dp[i][j][a][b]表示用了i个男生,j个女生,任一连续的后缀区间内,男生比女生最多多a人,女生比男生最多多b人. 转移就是显然了. # include <cstd ...
- Spark2.1.0之初识Spark
随着近十年互联网的迅猛发展,越来越多的人融入了互联网——利用搜索引擎查询词条或问题:社交圈子从现实搬到了Facebook.Twitter.微信等社交平台上:女孩子们现在少了逛街,多了在各大电商平台上的 ...
- POJ3686:The Windy's——题解
http://poj.org/problem?id=3686 题目大意: 有n个订单m个厂子,第i个订单在第j个厂子所需时间为zij,一个厂子做一个订单时不能做其他的订单. 求订单平均时间最小值. — ...
- maven打包jar源码至私服
1. setting文件 配置私服中设置的用户和密码 <servers> <server> <id>releases</id> <username ...
- Ajax请求回调函数没有被调用
$.ajax({ type:"post", url:"http://172.16.41.91:8080/FcsServletSSM/users ...
- 任务调度 Quartz 学习(一) SimpleTrigger
概述: 在实际开发过程中,会遇到很多任务调度的需求. 比如说:某网站要在每周一上午9点更新网站数据,并发邮件通知用户: 再比如某论坛需求:每隔半个小时生成精华文章的RSS文件,每天凌晨统计论坛用户的积 ...