知识点查缺补漏贴01-进程间通讯之mmap文件共享

引文:

  个人名言:“同一条河里淹死两次的人,是傻子,淹死三次及三次以上的人是超人”。经历过上次悲催的面试,决定沉下心来,好好的补充一下基础知识点。本文是这一系列第一篇:进程间通讯之mmap。

一、概念:什么是mmap?

  通过共享存储实现进程间通讯是一个主要的进程间通讯的方式。它包括磁盘文件的共享和内存的共享,以前总是关注内存的共享,而忽略了磁盘文件的共享,也就是这里要讲的mmap。mmap地址映射是Linux系统提供的一种功能强大的系统调用,最典型的应用是用于显卡内存的映射。同样,对于普通的硬盘文件也可以进行mmap系统调用。mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。

注:实际上,mmap()系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而Posix或系统V的共享内存IPC则纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。

函数原型如下所示:

       #include <sys/mman.h>

       void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);  //建立映射

       int munmap(void *start, size_t length);  //解除映射

二、参数说明:

  start: 起始虚拟地址,是用户期望使用的虚拟地址,如果进程的虚拟地址空间允许,那么会优先使用该地址。注意:该虚拟地址必须按页尺寸对齐。

      length:映射的长度。

      prot:期望的内存保护,注意不要和打开文件时的属性冲突。属性有PROT_EXEC、PROT_READ、PROT_WRITE、PROT_NONE,分别为可执行、可读、可写、不可访问。

      flags:指明映像对象的类型。类型有:MAP_FIXED(只使用指定的start虚拟地址)、MAP_SHARED(与其他进程共享该映射)、MAP_PRIVATE(创建一个写拷贝的映射,保持数据不影响原有文件)。

      fd: 打开的文件句柄。

      offset: 指明在文件中的偏移,注意:偏移也必须按页尺寸对齐。     

    其中最难理解的是start参数,它填入的是程序员期望使用的虚拟地址。如果该虚拟地址不冲突,那么mmap系统调用返回的值就应该是该虚拟地址。

三、代码实例

本例是打开一个普通的文件,对其进行mmap,然后读取文件内容:

#include <sys/mman.h> /* for mmap and munmap */
#include <sys/types.h> /* for open */
#include <sys/stat.h> /* for open */
#include <fcntl.h>     /* for open */
#include <unistd.h>    /* for lseek and write */
#include <stdio.h>
int main(int argc, char **argv)
{
    int fd;
    char *mapped_mem, *p;
    int flength = 1024;
    void * start_addr = 0;
    if(argc<2)
        {
            printf("please input filename\r\n");
            return 0;
        }
    fd = open(argv[1], O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    flength = lseek(fd, 1, SEEK_END);
    write(fd, "\0", 1); /* 在文件最后添加一个空字符,以便下面printf正常工作 */
    lseek(fd, 0, SEEK_SET);
    mapped_mem = mmap(start_addr, flength, PROT_READ,        //允许读
    MAP_PRIVATE,       //不允许其它进程访问此内存区域
    fd, 0);
    /* 使用映射区域. */
    printf("%s\n", mapped_mem); /* 为了保证这里工作正常,参数传递的文件名最好是一个文本文件 */
    close(fd);
    munmap(mapped_mem, flength);
    return 0;
}

四、输出结果:新建文件1.txt 随意输入一些内容即可

[zhangzl@localhost mmap]$ ./ex01 1.txt
2
hello
world.

时间: 2024-08-02 13:17:30

知识点查缺补漏贴01-进程间通讯之mmap文件共享的相关文章

知识点查缺补漏贴03:单机最大进程数,线程数和Socket连接数

前言: 参加Unix/Linux相关高级研发职位时,是否经常会被文档,单机允许最大进程数.线程数和Socket连接数,而你却感到束手无措呢?本文给你一个最为详细的答案. 一.最大进程数 运行Linux ulimit -a指令,我们可以看到:max user processes =1024 运行结构如下图所示: [root@localhost ~]# ulimit unlimited [root@localhost ~]# ulimit -a core file size (blocks, -c)

知识点查缺补漏贴02:Linux环境fork()函数详解

引言 先来看一段代码吧, #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { pid_t pid = fork(); if(pid < 0){ fprintf(stderr,"error!"); }else if(0 == pid){ fprintf(st

ruby查缺补漏

<Programming Ruby中文版>前3部分我并不准备细看,毕竟我接触ruby也有一段时间了,只准备快速地掠过一遍,查缺补漏:重点放在第3部分的核心内容上,至于第四部分的参考手册更多作为工具书了.仅在此记录下一些值的注意的东西. 1.全局变量$_,默认当gets方法返回输入的行时,同时保存在全局变量$_,并且正则表达式如果作为条件语句(if或者while)时默认是跟这个全局变量进行匹配,而print参数为空时也是打印这个全局变量.这是早期ruby向perl语言学习的结果.可以看看这个例子

进程间通讯问题,内存共享的实现

问题描述 需要在多个进程传输数据,其实一个检测进程一直获取检测的数据,供其他进程及时读取使用,数据库不是很大,但是数据更新非常的频繁,考虑到效率问题,不知道用什么方法实现?暂时决定采用内存共享的方式实现.希望各位大虾多加指点.具体怎么实现比较好?需要注意哪些地方?如果有类似的源代码参考就最好了. 解决方案 解决方案二:方案1.使用WM_COPYDATA消息方案2.使用WriteProcessMemory(),ReadProcessMemory()访问其他进程的内存方案3.使用内存镜像文件解决方案

PHP中实现进程间通讯

进程 PHP中实现进程间通讯 邱文宇   本文将讨论在PHP4环境下如何使用进程间通讯机制--IPC(Inter-Process-Communication).本文讨论的软件环境是linux+php4.0.4或更高版本.首先,我们假设你已经装好了PHP4和UNIX, 为了使得php4可以使用共享内存和信号量,必须在编译php4程序时激活shmop和sysvsem这两个扩展模块. 实现方法:在PHP设定(configure)时加入如下选项. --enable-shmop --enable-sysv

在PHP中实现进程间通讯

本文将讨论在PHP4环境下如何使用进程间通讯机制--IPC(Inter-Process-Communication).本文讨论的软件环境是linux+php4.0.4或更高版本.首先,我们假设你已经装好了PHP4和UNIX, 为了使得php4可以使用共享内存和信号量,必须在编译php4程序时激活shmop和sysvsem这两个扩展模块. 实现方法:在PHP设定(configure)时加入如下选项. --enable-shmop --enable-sysvsem  这样就使得你的PHP系统可以处理

NetBSD进程间通讯系统分析

简单的进程间通讯: 管道 管道是 UNIX 最传统, 最简单, 也是最有效的进程间通讯方法. NetBSD 处理管道的代码在 kern/sys_pipe.c, 它的读写函数作为 file 结构的 fileops 挂载, 并在 read(2), write(2) 时被调用. 管道创建 pipe(2) 的响应函数实 sys_pipe(). 它首先两次调用 pipe_create(), 第一次申请读端口将调用 pipespace() 申请一个用作缓冲区的内核地址空间 (回忆 BsdSrcUvm, su

Linux 进程间通讯共享内存方式

共享内存方式:从物理内存里面拿出来一部分作为多个进程共享. 共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入数据,共享这个内存的所有进程都可以立即看到其中内容. 共享内存实现步骤: 一.创建共享内存,使用shmget函数. 二.映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数. 创建共享内存shmget: intshmget(key_t key, size_t size, int shmflg) 功能:得到一个共享内存标识符或创建一个共享内存对象并

c++进程间通讯(共享内存)时

问题描述 c++进程间通讯(共享内存)时 我的需求:一个进程批量的数据不间断的存入差不多每秒有400k的数据这样子(不一定是一次存入的,可能是分几次),而另一个内存要从共享内存中读取这些数据,读取完就释放那块内存. 如何使共享的内存具有一定的数据结构,如同stl中的vector那样. 解决方案 需要自己做序列化,反序列化,把数据转回vector.自己定义格式等,知道多大一块内存数据表示一个vector的元素.然后一个个获取,存入vector 解决方案二: 如何使共享的内存具有一定的数据结构?共享