zoukankan      html  css  js  c++  java
  • 第3章 文件I/O(7)_高级文件操作:存储映射

    8. 高级文件操作:存储映射

    (1)概念:

      存储映射是一个磁盘文件存储空间的一个缓存映射,对缓存数据的读写就相应的完成了文件的读写。

     

    (2)mmap和munmap函数

    头文件

    #include<sys/types.h>

    #include<sys/mman.h>

    函数

    void* mmap(void* addr, size_t length, int prot, int flags,

                          int fd, off_t offset);

    int munmap(void* addr, size_t length);

    返回值

    mmap成功时返回映射区的起始地址,munmap成功为0,两者出错均返回-1。

    功能

    mmap:I/O使一个磁盘文件与存储空间中的一个缓存相映射。

    Munmap:解除映射。

    参数

    (1)addr:存储映射区的起始地址,通常设为0,让系统自动分配

    (2)length:需要映射的字节数。

    (3)prot:保护策略

      ①PROT_READ:映射区可读;②PROT_WRITE:映射区可写;

      ③PROT_EXEC:映射区可执行;④PROT_NONE:映射区不可访问。

    (4)flags:

      ①MAP_FIXED:返回地址必须等于addr,不鼓励使用

      ②MAP_SHARED:存储操作立刻修改映射文件内容。

      ③MAP_PRIVATE:存储操作导致创建映射文件的副本,并对副本读写。

    (5)offset:映射字节在文件中的偏移量

    备注

    (1)mmap函数从缓存中获取数据,就相当于读文件中相应的字节。与其类似,将数据存入缓存,则相应字节就自动地写入文件。这样,就可以在不使用read和write的情况下执行I/O

    (2)子进程继承父进程的存储映射区

    【编程实验】存储映射实现文件写入

    //file_map.c

    #include <unistd.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/mman.h>
    #include <string.h>
    
    int main(int argc, char* argv[])
    {
        if(argc < 2){
            printf("usage: %s file
    ",argv[1]);
            exit(1);
        }
    
        int fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC);
        if(fd < 0){
            perror("open error");
            exit(1);
        }
    
        //定位到文件尾部第26个字节的位置,并创建一个空洞文件
        lseek(fd, 25, SEEK_END);//定位第26个字母Z,所在的位置
        write(fd, "0", 1);   //先写入一个"0",以后会被字母Z覆盖
    
        //对文件的“空洞”区进行存储映射
        char* addr = mmap(0,     //映射区起始地址由系统自动分配
                          26,    //映射的字节数
                          PROT_WRITE, 
                          MAP_SHARED,
                          fd,
                          0);    //从指定的文件偏移量处开始映射
    
        //修改存储映射区的内容(会同步到文件中去)
        int i = 0;
        for(i=0; i<26; i++)
        {
            *(addr + i) = 'A' + i; //往空洞区写入26个大写字母
        }
        
        printf("write success
    ");
    
        //解除映射
        munmap(addr, 0);
        close(fd);
    
        return 0;
    }

    【编程实验】存储映射实现文件的拷贝

    //cp_map.c

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <string.h>
    
    int main(int argc, char* argv[])
    {
        if(argc < 3){
            printf("usage: %s srcfile, destfile
    ", argv[0]);
            exit(1);
        }
    
        int srcfd = open(argv[1], O_RDONLY);
        if (srcfd < 0)
        {
            perror("open error");
            exit(1);
        }
    
        int dstfd = open(argv[2],
                         O_RDWR |  O_CREAT | O_TRUNC, 0777);
        if(dstfd < 0 )
        {
            perror("open error");
            exit(1);
        }
    
        off_t len = lseek(srcfd, 0, SEEK_END); //源文件的长度
        printf("len: %ld
    ", len);
        
        //源文件映射到内存
        char* addr1 = mmap(0, len, PROT_READ, MAP_SHARED, srcfd, 0);
        if(addr1 < 0)
        {
            perror("mmap error");
            exit(1);
        }
        
        //在目标文件中,首先创建一个空洞文件
        lseek(dstfd, len-1, SEEK_SET);
        write(dstfd, "0", 1); //这个0会被后面复制而来的文件内容覆盖
    
        //目标文件映射到内存
        char* addr2 = mmap(0, len, PROT_WRITE, MAP_SHARED, dstfd, 0);
        if(addr2 < 0)
        {
            perror("mmap error");
            exit(1);
        }
         
        //存储映射区的复制,并同步到目标文件中
        memcpy(addr2, addr1, len); //拷addr1内容拷到addr2中
        
        printf("copy success!
    ");
    
        //撤销映射
        munmap(addr1, 0);
        munmap(addr2, 0);
        
        close(srcfd);
        close(dstfd);
    
        return 0;
    }
  • 相关阅读:
    ByteArrayInputStream(字节数组输入流) 示例
    ASP.NET 页面对象模型
    HTML常用标记
    [elementui]上线iconfont乱码
    time与timeEnd测试运行时间
    放大镜效果
    canvas
    [css] 样式列表
    千分符
    centos源失败
  • 原文地址:https://www.cnblogs.com/5iedu/p/6344880.html
Copyright © 2011-2022 走看看