zoukankan      html  css  js  c++  java
  • 【Linux编程】存储映射I/O

    存储映射I/O使一个磁盘文件与存储空间中的一个缓冲区相映射,对缓冲区的读、写操作就是对文件的读、写操作,从而能够不再使用read、write系统调用。

    将文件映射到存储区的函数由mmap完毕,函数原型例如以下:
    #include <sys/mman.h>
     
    /* 成功返回映射区起始地址,出错返回MAP_FAILED */
    void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);
    


    參数说明:
    • addr:指定映射存储区的起始地址,通常为0表示由系统选择起始地址。
    • len:须要映射的字节数。
    • prot:对映射存储区的保护要求,不能超过open文件时的权限。
      • PROT_READ:映射区可读
      • PROT_WRITE:映射区可写
      • PROT_EXEC:映射区可运行
      • PROT_NONE:映射区不可訪问
    • flag:影响映射存储区的属性。
      • MAP_FIXED:返回值必须等于addr,不利于移植。不鼓舞使用。
      • MAP_SHARED:表示存储操作相当于对该文件的write。
      • MAP_PRIVATE:对映射区的存储操作导致创建该映射文件的一个私有副本。
    • filedes:指定要被映射的文件描写叙述符,映射之前须要先打开该文件。
    • off:要映射字节在文件里的起始偏移量。通常为0。

    存储映射例如以下所看到的:


    測试代码:
    #include <stdio.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <string.h>
     
    #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
     
    int main(int argc, char *argv[])
    {
        int fdin, fdout;
        void *src, *dst;
        struct stat statbuf;
     
        if (argc != 3)
        {
            printf("usage: %s <fromfile> <tofile>
    ", argv[0]);
            return -1;
        }
     
        fdin = open(argv[1], O_RDONLY);
        fdout = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, FILE_MODE);
     
        fstat(fdin, &statbuf);
     
        lseek(fdout, statbuf.st_size - 1, SEEK_SET);
        write(fdout, " ", 1);   /* lseek偏移量大于文件长度时。写操作将加长文件 */
     
        src = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fdin, 0);
        dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdout, 0);
     
        memcpy(dst, src, statbuf.st_size);  /* 数据复制 */
     
        munmap(src, statbuf.st_size);
        munmap(dst, statbuf.st_size);
     
        return 0;
    }


    此函数实现了文件内容之间的拷贝。

    lseek + write的组合操作使得目标文件的大小添加到和源文件大小同样。由于当lseek设置的文件偏移量大于文件当前长度时。下一个写操作将会使文件增大。假设没有对目标文件扩大。那么进程会接收到SIGBUS信号。表示存储区中有地址无法映射到文件里。


    mmap实际上是将包括文件内容的内核缓冲区映射到应用程序地址空间,然后用memcpy直接进行数据的拷贝。其优势在于避免了类似read、write系统调用,在内核空间和用户空间之间的数据传递。

    參考:
    《unix环境高级编程》 P390-P395.
  • 相关阅读:
    cocos2d-x Tests讲解 Particle System(粒子系统)
    c++ 知识点
    详解C/C++函数指针声明
    VS中的路径宏 vc++中OutDir、ProjectDir、SolutionDir各种路径
    cocos2d-x学习知识点记录
    Ogre实现简单地形
    Ogre内部渲染流程分析系列
    gcc/g++编译
    gcc和g++的区别
    Hack with rewrite
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5093182.html
Copyright © 2011-2022 走看看