linux共享内存之mmap

这应该可以算得上是IPC的一种,虽然效率可能并没有其它IPC方式高.

看到map很容易联想到映射.的确,mmap就是一种映射方式,将打开的文件和一段连续的内存做映射.使得对内存进行操作即可以实现对文件的读写,反过来,也就是说,可以通过这种方式来达到进程通信.

mmap系列涉及三个函数.

void * mmap(void *buf, size_t len, int prot, int flag, int fd, off_t offset);

此函数建立一个共享内存,prot即为权限,可选值有PROT_READ, PROT_WRITE, PROT_EXEC, PROT_NONE.顾名思义,就不多说了.

flag即为共享内存作用范围.部分可取值为MAP_SHARED(进程共享,即当做出了修改,会写回到文件), MAP_PRIVATE(私有,即不会影响到文件), MAP_FIXED(一般情况下,buf参数置为NULL,由系统来分配地址,但是如果指定了这个字段,buf不能为空,否则core dump).

int msync(void *buf, size_t len, int flags);

此函数同步共享内存与文件的值,flags可取如下值,MS_ASYNC(同步), MS_SYNC(异步), MS_INVALIDATE(从文件中读回数据).

munmap(void* buf, size_t len);

此函数关闭共享内存.


使用这些常用的选项写一个简单的小程序.

#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>

typedef struct 
{
    int integer;
    char string[24];
}RECORD;

#define NRECORD 5

int main(int argc, char ** argv)
{
    RECORD *mapped;
    int i, f;
    
    f = open("record.dat", O_RDWR);
    mapped = (RECORD*)mmap(0, sizeof(RECORD) * NRECORD, PROT_READ | PROT_WRITE, MAP_SHARED, f, 0);

    printf("********************first of all***********************\n");
    for (i = 0; i < NRECORD; i++)
    {
        printf("record (%d) is %s\n", (mapped + i)->integer, (mapped + i)->string);
        (mapped + i)->integer += 100;
        snprintf((mapped + i)->string, 24, "RECORD-%d", (mapped + i)->integer);
    }

    msync((void *)mapped, sizeof(RECORD) * NRECORD, MS_INVALIDATE);   //MS_INVALIDATE MS_ASYNC MS_SYNC 这三个宏都可以达到更新文件的效果.不晓得三者的区别.

    printf("********************second of all***********************\n");
    for (i = 0; i < NRECORD; i++)
    {
        printf("record (%d) is %s\n", (mapped + i)->integer, (mapped + i)->string);
        (mapped + i)->integer += 100;
        snprintf((mapped + i)->string, 24, "RECORD-%d", (mapped + i)->integer);
    }
    msync((void*)mapped, sizeof(RECORD) * NRECORD, MS_ASYNC);

    printf("********************third of all***********************\n");
    for (i = 0; i < NRECORD; i++)
    {
        printf("record (%d) is %s\n", (mapped + i)->integer, (mapped + i)->string);
        (mapped + i)->integer += 100;
        snprintf((mapped + i)->string, 24, "RECORD-%d", (mapped + i)->integer);
    }

    munmap((void*)mapped, sizeof(RECORD) * NRECORD);

    return 0;
}

这三个函数在对文件进行操作的时候,其实优点还是很明显的.但是说到用来共享内存,相信这绝对不是一个好的选择.

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。