细说linux IPC(三):mmap系统调用共享内存
【版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途】
前面讲到socket的进程间通信方式。这样的方式在进程间传递数据时首先须要从进程1地址空间中把数据复制到内核,内核再将数据复制到进程2的地址空间中,也就是数据传递须要经过内核传递。这样在处理较多数据时效率不是非常高。而让多个进程共享一片内存区则攻克了之前socket进程通信的问题。共享内存是最快的进程间通信 。将一片内存映射到多个进程地址空间中,那么进程间的数据传递将不在涉及内核。
共享内存并非从某一进程拥有的内存中划分出来的。进程的内存总是私有的。共享内存是从系统的空暇内存池中分配的,希望訪问它的每一个进程连接它。这个连接过程称为映射。它给共享内存段分配每一个进程的地址空间中的本地地址。
mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后。进程能够向訪问普通内存一样对文件进行訪问。不必再调用read(),write()等操作。
函数原型为:
- #include <sys/mman.h>
- void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
当中參数addr为描写叙述符fd应该被映射到进程空间的起始地址,当指定为NULL时内核将自己去选择起始地址,不管addr是为NULL,函数返回值都是fd所映射到内存的起始地址;
len是映射到调用进程地址空间的字节数,它 从被映射文件开头offset个字节開始算起,offset通常设置为0;
prot 參数指定共享内存的訪问权限。可取例如以下几个值的或:PROT_READ(可读) , PROT_WRITE (可写), PROT_EXEC (可运行), PROT_NONE(不可訪问)。该值常设置为PROT_READ | PROT_WRITE 。
flags由下面几个常值指定:MAP_SHARED , MAP_PRIVATE , MAP_FIXED,当中,MAP_SHARED(变动是共享的,对共享内存的改动全部进程可见) , MAP_PRIVATE(变动是私有的。对共享内存改动仅仅对该进程可见) 必选其一,而MAP_FIXED则不推荐使用 。
munmp() 删除地址映射关系。函数原型例如以下:
- #include <sys/mman.h>
- int munmap(void *addr, size_t length);
參数addr是由mmap返回的地址。len是映射区大小。
进程在映射空间的对共享内容的改变并不直接写回到磁盘文件里。往往在调用munmap()后才运行该操作。能够通过调用msync()实现磁盘上文件内容与共享内存区的内容一致。 msync()函数原型为:
- #include <sys/mman.h>
- int msync(void *addr, size_t length, int flags);
參数addr和len代表内存区,flags有下面值指定,MS_ASYNC(运行异步写), MS_SYNC(运行同步写),MS_INVALIDATE(使快速缓存失效)。当中MS_ASYNC和MS_SYNC两个值必须且仅仅能指定一个,一旦写操作排入内核。MS_ASYNC马上返回,MS_SYNC要等到写操作完毕后才返回。假设还指定了MS_INVALIDATE,那么与其终于拷贝不一致的文件数据的全部内存中拷贝都失效。
在使用open函数打开一个文件之后调用mmap把文件内容映射到调用进程的地址空间,这样我们操作文件内容仅仅须要对映射的地址空间进行操作。而无需再使用open。write等函数。
使用共享内存的步骤基本是:
open()创建内存段;
用 ftruncate()设置它的大小。
用mmap() 把它映射到进程内存,运行其它參与者须要的操作;
当使用完时,原来的进程调用 munmap()然后退出。
以下来看一个实现:
server程序创建内存并向共享内存写入数据:
- int sln_shm_get(char *shm_file, void **shm, int mem_len)
- {
- int fd;
- fd = open(shm_file, O_RDWR | O_CREAT, 0644);//1. 创建内存段
- if (fd < 0) {
- printf("open <%s> failed: %s\n", shm_file, strerror(errno));
- return -1;
- }
- ftruncate(fd, mem_len);//2.设置共享内存大小
- *shm = mmap(NULL, mem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); //mmap映射系统内存池到进程内存
- if (MAP_FAILED == *shm) {
- printf("mmap: %s\n", strerror(errno));
- return -1;
- }
- close(fd);
- return 0;
- }
- int main(int argc, const char *argv[])
- {
- char *shm_buf = NULL;
- sln_shm_get(SHM_IPC_FILENAME, (void **)&shm_buf, SHM_IPC_MAX_LEN);
- snprintf(shm_buf, SHM_IPC_MAX_LEN, "hello share memory ipc! i'm server.");
- return 0;
- }
client程序映射共享内存并读取当中数据:
- int main(int argc, const char *argv[])
- {
- char *shm_buf = NULL;
- sln_shm_get(SHM_IPC_FILENAME, (void **)&shm_buf, SHM_IPC_MAX_LEN);
- printf("ipc client get: %s\n", shm_buf);
- munmap(shm_buf, SHM_IPC_MAX_LEN);
- return 0;
- }
先执行server程序向共享内存写入数据,再执行客户程序。执行结果例如以下:
- # ./server
- # ./client
- ipc client get: hello share memory ipc! i'm server.
- #
共享内存不像socket那样本身具有同步机制,它须要通过添加其它同步操作来实现同步,比方信号量等。同步相关操作在后面会有相关专栏具体叙述。
本节源代码下载:
http://download.csdn.net/detail/gentleliu/8140487
最后今天祝各位单身程序员节日快乐!。!!!
细说linux IPC(三):mmap系统调用共享内存的更多相关文章
- Linux IPC实践(10) --Posix共享内存
1. 创建/获取一个共享内存 #include <sys/mman.h> #include <sys/stat.h> /* For mode constants */ #inc ...
- 细说linux IPC(四):posix 共享内存
[版权声明:尊重原创.转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 上一节讲了由open函数打开一 ...
- Linux进程IPC浅析[进程间通信SystemV共享内存]
Linux进程IPC浅析[进程间通信SystemV共享内存] 共享内存概念,概述 共享内存的相关函数 共享内存概念,概述: 共享内存区域是被多个进程共享的一部分物理内存 多个进程都可把该共享内存映射到 ...
- linux下的进程间通信之共享内存
概念:这种机制允许两个或多个进程通过把公共数据结构放入一个共享内存区来访问它们.如果进程要访问这种数据结构所在的共享内存区,就必须在自己的地址空间中增加一个新线性区,新线性区映射与这个共享内存区相关的 ...
- 【网络编程基础】Linux下进程通信方式(共享内存,管道,消息队列,Socket)
在网络课程中,有讲到Socket编程,对于tcp讲解的环节,为了加深理解,自己写了Linux下进程Socket通信,在学习的过程中,又接触到了其它的几种方式.记录一下. 管道通信(匿名,有名) 管道通 ...
- linux c编程:Posix共享内存区
Posix共享内存区:共享内存是最快的可用IPC形式.它允许多个不相关(无亲缘关系)的进程去访问同一部分逻辑内存.如果需要在两个进程之间传输数据,共享内存将是一种效率极高的解决方案.一旦这样的内存区映 ...
- 细说linux IPC(一):基于socket的进程间通信(上)
[版权声明:尊重原创.转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途] 在一个较大的project其中 ...
- 撸代码--linux进程通信(基于共享内存)
1.实现亲缘关系进程的通信,父写子读 思路分析:1)首先我们须要创建一个共享内存. 2)父子进程的创建要用到fork函数.fork函数创建后,两个进程分别独立的执行. 3)父进程完毕写的内容.同一时候 ...
- Linux系统编程——进程间通信:共享内存
概述 url=MdyPihmS_tWLwgWL5CMzaTrwDFHu6euAJJUAjKvlzbJmRw7RfhmkBWwAloo7Y65hLY-kQdHsbqWYP2wc2fk8yq"& ...
随机推荐
- mysql远程访问另一台主机数据库表,实现小表广播功能
1.打开navicat,打开任意一个连接,新建一个查询,输入命令 show engines,出现如下界面 2. 如果FEDERATED对应的Support值为NO,则找到C:\ProgramData\ ...
- python3--命名空间字典
命名空间字典 我们学到了模块的命名空间实际上是以字典的形式实现的,并且可以由内置属性__dict__显示这一点.类和实例对象也是如此:属性点号运算其实内部就是字典的索引运算,而属性继承其实就是搜索连结 ...
- HDU-4612 Warm up,tarjan求桥缩点再求树的直径!注意重边
Warm up 虽然网上题解这么多,感觉写下来并不是跟别人竞争访问量的,而是证明自己从前努力过,以后回头复习参考! 题意:n个点由m条无向边连接,求加一条边后桥的最少数量. 思路:如标题,tarjan ...
- BZOJ 4719 [Noip2016]天天爱跑步 ——树链剖分
一直以为自己当时是TLE了,但是再看发现居然WA? 然后把数组扩大一倍,就A掉了.QaQ 没什么好说的.一段路径分成两段考虑,上升的一段深度+时间是定值,下降的一段深度-时间是定值,然后打标记统计即可 ...
- Tomcat 调优技巧
Tomcat 调优技巧:1.Tomcat自身调优: ①采用动静分离节约Tomcat的性能: ②调整Tomcat的线程池: ③调整Tomcat的连接器: ④修改Tomcat的运行模式: ⑤禁用AJP连接 ...
- hdu3038 How Many Answers Are Wrong
TT and FF are ... friends. Uh... very very good friends -________-b FF is a bad boy, he is always wo ...
- Android 瘦身之道
Android 瘦身之道 ---- so文件 [TOC] 1. 前言 目前Android 瘦身只有几个方面可以入手,因为apk的结构就已经固定了. res 目录下的资源文件.(通常是压缩图片,比如 矢 ...
- 济南学习 Day 5 T3 pm
科普一下: φ函数的值 通式:φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),其中p1, p2……pn为x的所有质因数,x是不为0的整数.φ(1)= ...
- calc BZOJ 2655
calc [问题描述] 一个序列a1,...,an是合法的,当且仅当: 长度为给定的n. a1,...,an都是[1,A]中的整数. a1,...,an互不相等. 一个序列的值定义为它里面所有数的乘积 ...
- Java面试题集(六)
以下为框架补充部分: Struts 2中,Action通过什么方式获得用户从页面输入的数据,又是通过什么方式把其自身的数据传给视图的? Action从页面获取数据有三种方式: ①通过Action属性接 ...