我是靠谱客的博主 能干龙猫,这篇文章主要介绍用mmap函数建立存储映射区进行进程间通信,现在分享给大家,希望可以做个参考。

        内存映射区简介

        存储映射I/O (Memory-mapped I/O) 使一个磁盘文件与存储空间中的一个缓冲区相映射。从缓冲区中取数据,就相当于读文件中的相应字节;将数据写入缓冲区,则会将数据写入文件。这样,就可在不使用read和write函数的情况下,使用地址(指针)完成I/O操作。

        使用存储映射这种方法,首先应通知内核,将一个指定文件映射到存储区域中。这个映射工作可以通过mmap函数来实现。

        

mmap函数

  • 函数作用:建立存储映射区
  • 函数原型:void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
  • 函数返回值:  成功:返回创建的映射区首地址;   失败:MAP_FAILED宏
  • 参数:
    1. addr: 指定映射的起始地址, 通常设为NULL, 由系统指定
    2. length:映射到内存的文件长度
    3. prot: 映射区的保护方式, 最常用的:读:PROT_READ写:PROT_WRITE读写:PROT_READ | PROT_WRITE
  • flags: 映射区的特性, 可以是
    • MAP_SHARED: 写入映射区的数据会写回文件, 且允许其他映射该文件的进程共享。
    • MAP_PRIVATE: 对映射区的写入操作会产生一个映射区的复制(copy-on-write), 对此区域所做的修改不会写回原文件。
  • fd:由open返回的文件描述符, 代表要映射的文件。
  • offset:以文件开始处的偏移量, 必须是4k的整数倍, 通常为0, 表示从文件头开始映射。

例1:以用mmap进行父子进程通信:

        代码如下:

#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
using namespace std;

int main()
{
        //使用mmap函数建立共享映射区
        int fd = open("./test.log", O_RDWR);//打开文件,获取mmap的参数文件描述符
        if(fd<0)
        {
                perror("open error");
                return -1;
        }

        int len = lseek(fd, 0, SEEK_END);//打开的文件用lseek获取文件大小

        //函数原型:void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
        void * addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        //void * addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
        if(addr==MAP_FAILED)//函数调用失败,返回Linux所规定的宏
        {
                perror("mmap error");
                return -1;
        }
        close(fd);//创建映射区的过程中,隐含着一次对映射文件的读操作,将文件内容读取到映射区
        //映射区的释放与文件关闭无关,只要映射建立成功,文件可以立即关闭。

        //创建子进程
        pid_t pid = fork();
        if(pid<0)
        {
                perror("fork error");
                return -1;
        }
        else if(pid>0)
        {
                //void *memcpy(void *dest, const void *src, size_t n); 内存拷贝函数将后者的内容拷贝到前者
                memcpy(addr, "hello 你好!!", strlen("hello 你好!!"));
                wait(NULL);//回收子进程
        }
        else if(pid==0)
        {
                sleep(1);
                char *p = (char *)addr;//强制类型转换
                printf("[%s]", p);
        }

        return 0;
}

~                                                                                                                                                                                                                                  
~              

 运行结果如下:

 

 子进程打印出来父进程写入的字符串。

例2:进行没有血缘关系进程通信

进程A(执行写的功能):

//使用mmap函数完成两个不相干进程间通信
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
using namespace std;
int main()
{
        //使用mmap函数建立共享映射区
        //void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
        int fd = open("./mmap.log", O_RDWR);
        if(fd<0)
        {
                perror("open error");
                return -1;
        }

        int len = lseek(fd, 0, SEEK_END);

        //建立共享映射区
        void * addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        if(addr==MAP_FAILED)
        {
                perror("mmap error");
                return -1;
        }

        memcpy(addr, "0123456789", strlen("0123456789"));

        return 0;
}

进程B(执行读的功能):

#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
using namespace std;

int main()
{
        //使用mmap函数建立共享映射区
        //void *mmap(void *addr, size_t length, int prot, int flags,
    //              int fd, off_t offset);
        int fd = open("./mmap.log", O_RDWR);
        if(fd<0)
        {
                perror("open error");
                return -1;
        }

        int len = lseek(fd, 0, SEEK_END);

        //建立共享映射区
        void * addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
        if(addr==MAP_FAILED)
        {
                perror("mmap error");
                return -1;
        }

        char buf[64];
        memset(buf, 0x00, sizeof(buf));
        memcpy(buf, addr, strlen((char*)addr));
        cout << "buf==[" << buf << "]" << endl;

        return 0;
}

先执行A,随后执行B,保证读到写入的内容:

 看到[01123456789]已经写入 mmap.log中,实现了不相干进程之间的通信.

 

最后

以上就是能干龙猫最近收集整理的关于用mmap函数建立存储映射区进行进程间通信的全部内容,更多相关用mmap函数建立存储映射区进行进程间通信内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(119)

评论列表共有 0 条评论

立即
投稿
返回
顶部